Задать вопрос
  • Можно ли передать тип данных как параметр функции?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    В C - нет. В C++ можно воспользоватся шаблонами. Но если вопрос действительно про C, то надо передавать в функцию какой-нибуть enum где все возможные типы перечисленны. Или, как в scanf, передавать идентификатор типа в строке.
    Ответ написан
    6 комментариев
  • Множество с запросами?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ваше решение медленно считает сумму на отрезке. За O(n) - вы проходитесь по всему множеству. А все ваше рение будет O(n^2). Когда как это надо делать за O(log n) максимум. Ну посмотрите же на ограничения - n <= 10^5. Обычно n^2 работает ну до 10^4 максимум с огромным скрипом и натяжками.

    К сожалению, стандартными set'ами вы сумму на отрезке быстро не подсчитаете. Придется реализовывать сбалансированное бинарное дерево поиска, где в каждой вершине надо дополнительно хранить сумму всех значений в поддереве. Вот реализация дерева, но там сумма на отрезке не реализована. Однако, в статье расказанно, как это делать. Ищите на странице "на отрезке".

    Если бы числа в задаче был поменьше, то можно было бы использовать дерево отрезков. Это сильно проще реализуется. Но тут бы это потребовало массивы на 2*10^9 элементов.

    Edit: вообще, судя по нескольким вопросам от вас, у вас там задачи именно на реализацию бинарных деревьев поиска с дополнительными данными в вершинах. Вот если у вас следующая задача опять не пройдет по времени, то сначала убедитесь, что вы используете собственноручно написанное дерево поиска.
    Ответ написан
  • Как лучше\проще реализовать работу с серийными номерами\лицензиями чтобы не особо пиратили?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Единственный способ запретить нелецинзионное копирование вашей программы - это вынести что-то важное в серверную часть. Там логин/пароль пользователя, плюс проверки на отсутствие параллельных сессий.

    Все остальное ломается.

    Следующий плохой вариант: делать слепок системной информации, при активации лицензии подписывать его на сервере приватным ключем. Программа открытым ключем проверяет, что файл лицензии корректен (расшифровывает и смотрит, что системная информация совпадает).
    Ответ написан
    Комментировать
  • Почему код не проходит по тайм лимиту?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С такими ограничениями надо менять алгоритм. У вас наивная реализация за O(nq). А надо реализовывать rope за O(q log n).

    Какими-то стандартными контейнерами это не сделать вообще никак.

    Советую реализовывать декартово дерево по неявному ключу. Это самая простая реализация будет. Ну, а дальше вам надо будет это дерево разрезать на три части двумя Split, две крайние объеденить, разрезать это в новом месте и слить уже 3 части с вырезанным куском в середине.
    Ответ написан
  • Как работает данный алгоритм проверки числа на простоту и какой у него Big O??

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Это вроде как решето Эратосфена (только с багами).

    Этот цикл по идее помечает составными все числа, делящиеся на i (которое к этому моменту вроде как простое). Таким образом все составные числа должны быть помечены в массиве a.
    Тут есть оптимизация: помечаются только те числа, для которых i - делитель не больше корня. Иначе бы цикл был не от i*i а от i. Эту оптимизацию можно делать, потому что у каждого числа обязательно есть простой делитель не больше корня, а значит и такой цикл пометит все составные числа.

    Сложность тут O(n log(log n)) - Доказательство смотрите в википедии.
    Ответ написан
    Комментировать
  • Как классифицировать числовой ряд?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Это называется кластеризация. Вам надо разбить данные на 3 кластера. Метод ближайших соседей, упомянутый выше, подходит.

    Все-таки все эти методы кластеризации разработаны для более общего случая. А у вас тут данные одномерные и численные уже - так что все совсем просто.

    Во-первых, данные надо отсортировать, если уже не. А дальше у вас тут 2 переменные - (i,j) - первый и последний элемент в средней группе.i>0,j<n-1.

    Можно эти индексы тупо перебрать двумя вложенными циклами. А дальше надо считать какую-то целевую функцию - насколько хорошо кластеры выбраны и брать лучшее значение. Надо, чтобы внутри различие было поменьше, а между кластерами - побольше. Можно брать максимум разности в каждом кластере и делить на разницу между двума кластерами. Вот минимизируйте эту функцию.

    Но вообще можно, наверно, просто взять 2 максимальных промежутка между соседними числами и по ним разделить. В примере выше этот метод отлично разбивает на 3 группы: 1-103, 999-1001, 9000-9500

    Если разность между маленькими числами важнее разности между большими, то возьмите сначала логарифм от всех чисел и уже это разбивайте на группы.
    Ответ написан
    7 комментариев
  • Как исправить код?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Похоже проблема в непонимании параметров string::insert. Там передается индекс, в который и вставляется строка. Т.е. новые данные будут по этому индексу. Фактически, они вставляются перед символом на этой позиции.

    Оно уже делает ровно то, что вам надо, не нужно делать там k[i]-1 и разбирать отдельно случай k[i]==0.
    Ответ написан
    Комментировать
  • Почему вылазит link error(не видит вирутальные методы?)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Потому что шаблон.

    Надо или весь класс определять в хедере, или в array.cpp указывать компилятору генерировать инстанс шаблона с параметром, который нужен в другом cpp файле:
    using Array<int>;

    То же и для очереди.

    Происходит это потому, что компилятор генерирует шаблоны лениво - только когда они нужны. Вот, компилируя array.cpp он не видет вообще ни одного использования шаблона и не генерирует ничего. В каком-нибудь main.cpp у него есть объявление из array.h и использование шаблона. Он и генерирует объявления методов. Но определения-то нигде нет. Оно в array.obj должно быть по вашему замыслу, а там пусто.
    Ответ написан
    1 комментарий
  • Поиск кратчайшего пути в ориентированном графе с цветными вершинами и дугами?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Тут надо сделать из графа на N вершин граф на N^2 вершин. Граф-то совсем маленький. Каждая вершина нового графа соответствует паре вершин изначалного графа (x, y) и обозначает, что фишки стоят в вершинах x и y соответственно. Переходы в новом графе делаются из переходов в изначальном: из (x, y) можно перейти в (x, z), если в изначальном графе есть дуга y->z и ее цвет совпадает с вершиной x. Аналогично из (x,y) можно перейти в (z,y), если есть дуга x->z и ее цвет совпадает с y.

    В этом графе уже можно любым известным вам способом искать путь. Только тут конечных вершин будет сразу много: это все пары (x,y), где x или у - конечная вершина в графе. Можно или добавить новую конечную вершину и соединить с ней все вот эти вот, или прямо в алгоритме исправить условие останова.

    Можно граф не хранить явно. Если у вас BFS, то храние в очереди сразу пару чисел. Внутри перебирайте переходы из первой а потом из второй вершины и делайте их только если условие на совпадение цвета выполняется. Ну и, все массивы хранящие расстояние и т.п. в алгоритме будут уже двумерные.
    Ответ написан
    Комментировать
  • Как найти такую вершину заданного графа, которая принадлежит каждому пути между двумя выделенными?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Все такие вершины являются точками сочленения. Ведь, удалив такую вершину из графа больше не будет пути между двумя вершинами, а значит граф развалился на новые компоненты связности. Есть алгоритм на основе Dfs, который их ищет. Это все работает за O(V+E). Предложенный вами алгоритм с удалением по одной вершине вполне себе работает, но будет медленнее: O(V(V+E)). Для небольших графов может и подойдет.

    Потом надо найти путь между заданными вершинами и вывести в ответ точки сочленения. Лучше ищите путь тем же DFSом, что и ищите точки сочленения. Так путь будет идти по дереву DFS. Надо найти в нем LCA двух искомых точек (Пик пути, после которого он пойдет вниз в другую ветку).

    Важно, выводить надо не все точки сочленения, а только те, у которых из следующей вершины в пути, она же будет ребенком в дереве DFS, нельзя вернутся назад выше текущей точки сочленения. Т.е. точка назначена алгоритмом точкой сочленения из-за ребенка именно в сторону искомой вершины.
    Ответ написан
    Комментировать
  • Почему выбивает исключение на моменте деления изображения на равные блоки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Наверно, в коде еще есть ошибки, но вот тут:
    vector <double> variances;
    for (int i = 0; i < num_blocks; i++) {
        Scalar mean, stddev;
        meanStdDev(block[i], mean, stddev);
        variances[i] = stddev.val[0];
    }


    Вы записываете в пустой вектор variances по индексу i. Надо или делать push_back в вектор, или выделить его сразу размера num_blocks. Например, так:
    vector <double> variances(num_blocks);

    Еще перепроверьте, что у вас rows/cols не перепутано.
    Ответ написан
    Комментировать
  • Есть ли флаг компиляции gcc, чтобы неявное приведение типов выводилась как ошибка?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    -Wconversion -Warith-conversion
    Ответ написан
    Комментировать
  • Почему не считывает все нажатия вне event loop SFML?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    pollEvent возвращает сообщение из очереди, пока они там есть. В очереди их может оказаться несколько. Именно поэтому там цикл while. А код за циклом обрабатывает только одно - последнее - сообщение. Судя по наблюдаемому вами поведению, в очереди оказывается несколько сообщений.
    Ответ написан
  • Как отправить клик мышью в чужое SDL окно не двигая системную мышь через winapi?

    wataru
    @wataru Автор вопроса
    Разработчик на С++, экс-олимпиадник.
    После более пристального ковыряния в spy++ я выяснил, что чужое окно получает WM_MOUSELEAVE после каждого моего SendMessage с WM_MOUSEMOVE или WM_LBUTTONDOWN/UP.

    Видимо, оно подписывается у системы на это через TrackMouseEvent.

    Это лишнее сообщение все портит и приходит даже если посылать сообщения через SendMessage без задержек.

    Похоже, придется ковырятся с dll injection, чтобы перехватывать WM_MOUSELEAVE и игнорировать его.
    Ответ написан
    Комментировать
  • Почему не работает GetPixel?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    GetPixel принимает сначала x, потом y. У вас там Height и Width не в том порядке переданы.

    Это будет ошибкой, если одна из сторон более чем в 2 раза больше другой. Это может быть, если у вас широкоформатный монитор.

    У вас там битмап сохраняется в sceen2.png - оно там что-то сохранило вообще? Иначе проблема может быть не GetPixel, а с самим хБитмапом.

    Edit:

    Еще проблема может быть с масштабированием. В результате GetSystemMetrics(SM_CYSCREEN) возвращает не то, что вам надо и BitBlt не срабатывает из-за слишком большого размера.

    Попробуйте вызвать SetProcessDPIAware.

    Еще может быть проблема, что вы SelectObject делаете 2 раза с одним и тем же membit. Надо во второй раз что-то другое подставлять, чтобы HBitmap освободить. Иначе оно, похоже, так и остается привязано к DC.

    Вот мой рабочий код:
    HBITMAP GameManager::GetScreenshot(HWND window) {
    	HDC hScreenDC = GetDC(window);
    	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
    	RECT window_rect;
    	GetClientRect(window, &window_rect);
    	int width = window_rect.right - window_rect.left;
    	int height = window_rect.bottom - window_rect.top; 
    	int result_width = width;
    	int result_height = height;
    	
    	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, result_width, result_height);
    	HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hBitmap));
    	StretchBlt(hMemoryDC, 0, 0, result_width, result_height, hScreenDC, 0, 0, width, height, SRCCOPY);
    	hBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hOldBitmap));
    	DeleteDC(hMemoryDC);
    	DeleteDC(hScreenDC);
    	return hBitmap;
    }
    Ответ написан
    1 комментарий
  • Как растягивать прямоугольники до полного замощения области?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Не знаю, насколько оптимальное решение это будет давать, но раздувайте прямоугольники по чуть-чуть.

    Пусть у прямоугольников будут степени свободы - верх,лево,низ,право. Изначально все прямоугольники раздуваются во все 4 стороны.

    Дальше, представьте, что каждый прямоугольник раздувается на 1 пиксель во все стороны за 1 тик.

    Перебрав все пары прямоугольников вы можете для них подсчитать через какое время эта парочка столкнется. Важно, надо считать только варинаты, где прямоугольники раздуваются друг на встречу другу (хотя бы один из пары), а то у вас может все время быть время 0 - два прямоугольника сейчас касаются.

    Найдите минимальное время для всех пар. "Отмотайте" это время вперед - раздуйте все прямоугольники на это количество пикселей по всем активным степеням свободы. У двух пересекающихся отберите свободу раздуваться в направлениях, где они коснулись. Если они коснулись по углу, то у вас это будет событие: или они встретились по горизонтали, или по вертикали. Именно эти степени свободы и отбираете.

    Повторяйте пока есть хоть одна степень свободы где-то.

    Ну и еще надо учитывать пересечения с гарницей поля - точно так же. Считаете время до столкновения.

    Может быть так, что пройдет время 0, если куча прямоугольников коснутся в одно и то же время. Это нормально, вы не перематывая время в обработке этого события дезактивируете какие-то степени свободы у каких-то прямоугольников.

    Можно просто после каждого столкновения снова искать минимум по всем парам прямоугольников. Можно это соптимизировать знатно через приоритетную очередь, но вряд ли у вас там тысячи прямоугольников и вам это надо делать.

    Еще прикол, если прямоугольники пересекутся через пол тика - между ними всего один пиксель. Тут надо будет двигать только один из двух, скажем, с тот у кого номер меньше.

    В примере с картинки вы через 0 тиков зафиксируете, допустим, вертикальные границы и потом найдете. что через какое-то время один из прямоугольников упрется в стену. Раздуете оба прямоугольника, зафиксируете упершийся. Дальше, если все симметрично, то второй прямоугольник через 0 тиков тоже упрется в стену.

    Правда у этого метода есть проблема Например, вот такая картинка:
    AA.B
    ...B
    C...
    C.DD


    Тут прямоугольники можно чуть чуть раздуть до упирания, но при определенных пропорциях в центре останется пустое место, при чем все 4 окна будут сцеплены между собой. Не уменьшая изначальные окна его никак не убрать.
    Ответ написан
    Комментировать
  • Реализация лабиринта по алгоритму Уилсона. Как сделать это в C# WinForms?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    В чем проблема перевести с lua на C#?

    Там в алгоритме ничего сверх сложного и какой-то встроенной библиотеки не используется. Понятно, что MazeGrid - это двумерный массив? Aux - это класс с методами createGrid (возвращает двумерный массив класса с полями visited, right_wall, bottom_wall), wilson (реализация алгоритма) и всякие вспомогателные hashKey/deHashKey. Еще есть поля width/height/sx/sy.

    Сам алгоритм в wilson() использует циклы while и for, if, elseif - все это переводится на C# не задействуя мозг вообще. Чисто механически. Ну, разве что о типах переменных чуть чуть подумать придется. Но, ясно же, что dir - это строка, isMoved - bool.

    Потом, когда вы это все переведете, можно начинать улучшать код. Типа вместо строк для направлений использовать enum.
    Ответ написан
    Комментировать
  • Вычислить исходные величины на основе измерений с погрешностью - как называется и решается такая задача?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Это называется кластеризация.

    Восстановить точное значение вы никогда не сможете, но можно взять среднее в каждом кластере. Такими измерениями занимается статистика
    Ответ написан
    Комментировать
  • Можно так сделать с interface?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По уму, вам надо продумать ваш интерфейс. И тогда подобных извращений не понадобится. Дабавьте туда какой-нибудь способ для итерации по структуре данных для вывода. Или вообще сделайте метод ToString, который бы возвращал строковое представление внутренней структуры для вывода. Это все, естественно, виртуальные публичные методы, переопределенные в двух реализациях.

    То же и со вводом. Если надо как-то во внутренности очереди залезать и обычными push это не сделать, то, например, передавайте в метод CreateFromData() вектор введенных пользователем значений.
    Ответ написан
    Комментировать
  • Почему скалярное произведение не нормализованных и коллинеарных векторов разное при изменении их точек?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Ну, скалярное произведение вектора самого на себя - даст квадрат его длины по определению (|a|*|a|*cos(0)). Если менять точки - меняется длина вектора - меняется скалярное произведение.
    Ответ написан
    Комментировать