Блог пользователя Krasnokutskiy

Автор Krasnokutskiy, 12 лет назад, По-русски

Добрый день комьюнити) В Украине среди школьников проводится конкурс МАН, который заключается в написании научных работ, я придумал тему, и хотел бы узнать, будет ли это сильно баян... Пожалуйста, сильно не агртесь, т.к. это работа школьника. Собственно, работа (еще не написанная) будет посвящена структуре данных) Структура позволяет добавлять, находить и удалять элемент x в множестве S, за O(log(x)). Так же на множестве можно поддерживать все ассоциативные операции, такие как: min, max, gcd, xor и прочие (как в сете минимум)... Для этого, воспользуемся бинарным деревом (двоичный бор) и каждому ребру припишем 0 или 1, в зависимости от того левый это ребенок или правый. Предположим нам надо добавить число 116, тогда его двоичное представление 1110100, значит из корня мы идем вдоль ребер 0->0->1->0->1->1->1 и там ставим флаг, что такое число есть. Т.е. так будет выглядеть рекурсивный код:

class node
{
    node()
    {
        next[0] = next[1] = exist = 0;
    }
    node *next[2]; //левый и правый сын
    bool exist;
};

void includeElem(int addNum, node *current) //addNum - добавляемое число, current текущая вершина
{
    if (addNum == 0)
    {
        current->exist = 1;
        return;
    }    
    if (current->next[addNum & 1] == 0)
        current->next[addNum & 1] = new node();
    includeElem((addNum >> 1), current->next[addNum & 1]);
}

В силу того что структура не перестраивается, т.е. корню (и другим вершинам, в которые ведут ребра с пометкой 1) всегда будет соответствовать одно число (корню — 0), то можно ввести функцию на поддереве, как в дереве отрезков, т.е. собирать информацию с детей. Тогда если мы добавляем элемент, то значение этой функции может поменяться только на пути от добавляемой вершины, до корня, значит, когда мы будем возвращаться назад, то на всем пути нам просто надо будет обновить функцию f.

class node
{
    node()
    {
        next[0] = next[1] = exist = valueOfFunc = 0;
    }
    void update(int number) //число соответствующее этой вершине
    {
        **valueOfFunf = f(f(next[0]->valueOfFunf, next[0]->valueOfFunf), number); //тут еще надо проверить, существует ли вообще next[0/1], и если в эту вершину ведет ребро с пометкой нуль, тогда number хорошо бы поставить нейтральным элементом**
    }
    int valueOfFunc;
    node *next[2]; //левый и правый сын
    bool exist;
};

void includeElem(int addNum, node *current) //addNum - добавляемое число, current текущая вершина
{
    if (addNum == 0)
    {
        current->exist = 1;
        return;
    }    
    if (current->next[addNum & 1] == 0)
        current->next[addNum & 1] = new node();
    includeElem((addNum >> 1), current->next[addNum & 1]);
    **current->update();**
}

Так же памяти эта структура будет занимать O(n*log(maxNum)), где n — это количество элементов множества, а maxNum — это максимальное число в нем. Это не трудно заметить из того, что за одно добавление числа x мы добавляем O(log(x)), новых вершин, а т.к. добавлений n — то выходит итоговая асимптотика. Собственно, я бы хотел узнать, имеет ли эта тема на существовании в МАНе?

  • Проголосовать: нравится
  • +35
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Молодец, хорошая работа. Такую структуру я еще не встречал.

»
12 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

Замечательно!!! Обычно МАНы пишутся на пустые темы, копированные с википедии. А это серозная работа, достойная внимания. Я искренне надеюсь твою идею оценят)))!!! Удачи)!

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

круто. но это разве не бор? по крайней мере в решении задачи A тут: http://neerc.ifmo.ru/school/io/archive/20120225/problems-individual-20120225.pdf применялась подобноя идея. другое дело, что хранить в вершинах значение ф-ии — такого я не встречал

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

Похоже на сжатое дерево отрезков, построенное на [0..MaxValue]

»
12 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Это немного изменённое (из-за разной длины чисел) сжатое дерево отрезков на всех числах от 0 до maxNum. Любое сбалансированное бинарное дерево будет решать поставленную задачу лучше (log(n) вместо log(maxNum) и памяти O(n)). Конечно, у вас "бонус" в быстром времени работы для мелких чисел, но его тоже легко победить, если сделать log(maxNum) деревьев. Не знаю, что такое МАН, но советую вам улучшить вашу структуру — и реализация проще будет, и работать будет гораздо быстрее.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

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

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Ну оно у бинарных деревьев ни в чём не выиграет — там функция точно так же добавляется, храним в каждой вершине ответ для поддерева, при изменении пересчитываем.

      Если там участники действительно предлагают что-то в computer science, что в чём-то лучше всего существующего, — очень хотелось бы посмотреть на примеры работ, т.к. это довольно круто :)

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        Да, согласен, в бинарных деревьях тоже можно спокойно обновить значение функции. Но тогда в плюсы можно написать, что оно работает быстрее когда много маленьких чисел =)

        А по поводу работ на этом МАНе, там ооочень мало нормальных работ, почти нет. Конкурс проводится в 3 тура, заочный (ты им посылаешь письменный вариант работы), контрольная (математика) и защита.. Ну и все там решает контрольная, если нормальная работа.. В прошлом году я пошел в "обучающие программы" и писал работу про визуализацию нейронных сетей с кнопочками "Создать", "Обучить", "Тестировать", свою нейро-сетку и эта лажа заняла 1-ое место. Но в этом году хочется написать что-то нормальное..

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          На маленьких числах вы тоже не обгоните бинарные деревья — как я написал в первом комменте, можно сделать log(maxNum) деревьев — по одному для каждой длины числа в битах. Тогда получим на операцию log(количества чисел в множестве той же длины, что и x), что <=log(x).

          Что там мало нормальных работ — я не удивлён, делать в науке что-то новое непросто; даже если там O(1) работ, которые в чём-то лучше всего существующего, — это уже очень круто.

»
12 лет назад, # |
Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

Оценку по памяти точнее определить как O(min(MaxNum,N*log(MaxNum))).

Минус в ограниченности: элементы — целые неотриц-ые числа, можно расширить и до вещетвенных, наверно, по той же схеме. Еще один минус что результаты этих полезных функций вычисляются только для строгих множеств элементов (которые опред-ся их двоичными представлениями)

Есть ли такое в Мане врядли тут кто-то может сказать, не проще им послать на рецензию?

По-моему уровень работы хороший для школьника и для Мана, но научной новизны конечно нет)