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

Автор neosnova, история, 3 года назад, По-русски

Вам дан массив из N<=10^5 целых чисел в интервале [1,K]. K<=50. Вы должны обработать M<=10^5 запросов 2-х видов :

1 i x — изменить значение i-го числа на x

2 — вывести длину кратчайшего непрерывного подотрезка массива, содержащего все целые числа от 1 до K

...

Тест 1
Тест2

P. S. Буду рад услышать любой совет и подсказку. Заранее спасибо.

P.P.S Решил, всем спасибо. Сдал решением alexsushin. Даже не понадобились 2 указателя : я поддерживал минимальное подходящее r (то есть сначала просто r присваивал максимуму из t[v * 2 + 1].pref[i] для всех i которых вообще нет в левой части, а потом проходился по отсортированному вектору t[v * 2].suff и "удалял" этот элемент, тогда левая граница нового отрезка — следующий элемент в векторе, и так как я удаляю последнее вхождение элемента на левом подотрезке, то надо пересчитать r = max(r, t[v * 2 +1].pref['элемент который удалил']). Суть в принципе та же, но не нужен дополнительный массив cnt и двигать указатели, а просто пересчет r.

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

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

Откуда задача?

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

    Задача с сайта dl.gsu.by

    Была на олимпиаде Гомельской области для учащихся 5-7 классов в апреле 2023 года.

    P.S если зарегистрируйтесь на сайте для быстрого поиска можно использовать ее id : 236405

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

Такое чувство, что можно легче, но...

тупой хинт
чуть менее тупой
вроде бы решение
  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится +3 Проголосовать: не нравится

    Правильно понимаю, что если побитовое ИЛИ двух детей равны 2 ^ k — 1, то мы спускаемся, как и влево, так и вправо?

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

      Решение, как я понял неправильное, тк не учитываю общие у детей биты.

      А так, — нет. Мы уже поднялись из детей и их ИЛИ получилось в 2^k-1. И только потом делаем бинпоиск (или спуск). В любом случае решение неправильное)

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

        Ну просто, не совсем понятно, что значит «Как только в какой-то вершине маска полностью заединичена смотрим на маски детей». Эту вершину надо найти. К тому же это не правда, что таких вершин Log(n)

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

Назовем отрезок хорошим, если он содержит все числа от 1 до К.

Будем поддерживать Дерево Отрезков, внутри вершины, отвечающую за отрезок [TL;TR] будем хранить структуру node, которая содержит следующие значения:

ans — минимальная длина хорошего отрезка на [TL;TR].

pref — вектор, содержащий первые вхождения чисел от 1 до К на [TL;TR].

suff — вектор, содержащий последние вхождения чисел от 1 до К на [TL;TR].

Как делать merge двух node {A, B}? Так как мы знаем минимальные хорошие отрезки в A и B, нужно найти минимальный отрезок, у которого левая граница в A, а правая в B. Можно показать, почему существует оптимальный хороший отрезок [L; R], что L принадлежит A.suff, а R принадлежит B.pref.

Доказательство: «Предположим, что R не принадлежит B.pref. Так как отрезок точно проходит через разрез между A и B (т.е. является префиксом B и суффиксом A), то элемент на позиции R встречается не впервые (по определению B.pref), следовательно можно подвинуть правую границу влево и хуже не станет. Доказательство, что L принадлежит A.suff аналогично.»

На основе этого можно написать решение с двумя указателя для поиска этого отрезка и попробовать улучшить через него ans. Достаточно очевидно, как поддерживать pref и suff. Так как мы содержим информацию только о различных числах, то длина pref и suff никогда не превышает K, следовательно каждая часть merge работает за O(K). Получается запрос изменения работает за O(K * log(N)), т.к. мы изменим node лишь в O(Log(N)) вершинах

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

    Большое спасибо. Мне правда пока что непонятно как двумя указателями пытаться пересчитывать ответ (чтобы это за K работало).

    Если Вам нетрудно, можете пожалуйста подробнее рассказать про эту часть решения?

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

      Идем 1 указателем с конца A.suff, а 2 указателем с начала B.pref. Можно завести, например, массив cnt[K],

      где cnt[i] = сколько раз встречается элемент с значением i.

      Когда двигаем 1 указатель с конца A.suff, возможно, одного элемента теперь нет в отрезке, поэтому двигаем 2 указатель в B.pref, чтобы этот элемент снова вернулся и меняем массив cnt.