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

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

909A - Генерация логина

Самое простое решение — сгенерировать все возможные логины (перебрав все пары непустых префиксов имени и фамилии и скомбинировав их) и выбрать из них первый по алфавиту.

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

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

909B - Отрезки

Рассмотрим участок координатной прямой [i, i + 1]. Очевидно, все отрезки, покрывающие этот участок, должны находиться в разных слоях. Для каждого из этих отрезков левый конец находится в одной из точек 0, 1, ..., i (i + 1 вариантов), а правый — в одной из точек i + 1, i + 2, ..., N (N - i вариантов). Итого отрезков, покрывающих участок [i, i + 1], будет Mi = (i + 1)(N - i) штук. Наибольшая из величин Mi для i = 0, ..., N - 1 даст нам оценку снизу для необходимого количества слоев.

Задача не требует разбиения отрезков на слои в явном виде, поэтому можно предположить, что эта оценка снизу — точная. max Mi можно найти за O(N), или можно заметить, что максимум достигается для (для центрального отрезка, если N нечетное, или одного из двух центральных, если N четное).

Ответ — .

Этот же ответ можно получить явным построением. Отсортируем отрезки в порядке неубывания их левых концов и затем в порядке возрастания их правых концов. Будем распределять отрезки по слоям жадно: если i — левый конец текущего отрезка, и участок [i, i + 1] свободен в каком-то слое, добавим текущий отрезок к этому слою; иначе начнем новый слой с этим отрезком.

и да, это наша задача с решением за O(1) :-)

909C - Отступы в Python

Эту задачу можно решить при помощи динамического программирования.

Рассмотрим все возможные программы, которые заканчиваются инструкцией i, записанной с отступом j. Обозначим количество таких программ dp[i][j].

Для первой инструкции dp[0][0] = 1, dp[0][j] = 0 для j > 0 (есть ровно одна программа, состоящая из одной инструкции, и она записана с нулевым отступом).

Рекуррентное соотношение для перехода к следующей инструкции в программе следует из описания инструкций: когда мы добавляем инструкцию i + 1, возможные значения отступа для нее зависят от возможных значений отступа инструкции i и от типа инструкции i. Если инструкция i — цикл, инструкция i + 1 должна иметь отступ на один больше предыдущей, поэтому dp[i + 1][0] = 0 и dp[i + 1][j] = dp[i][j - 1] для j > 0. Если инструкция i — простая инструкция, то команда i + 1 может быть частью тела любого из предшествующих циклов, и иметь любой отступ от 0 до отступа инструкции i. Если мы обозначим отступ инструкции i (простой инструкции) как k, отступ инструкции i + 1 как j, нам нужно просуммировать все случаи, для которых k ≥ j: .

Итоговый ответ будет общим количеством программ, заканчивающихся последней инструкцией с любым отступом: .

Сложность решения — O(N2).

909D - Разноцветные точки

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

Рассмотрим непрерывные группы точек одинаковых цветов. Одно действие удалит только точки на границах группы (за исключением точек на левой границе самой левой группы и правой границе самой правой группы, если в этих группах больше одной точки), остальные точки будут не затронуты. Если текущие размеры групп слева направо N1, N2, ..., NG - 1, NG, то размеры групп после выполнения первого действия — N1 - 1, N2 - 2, ..., NG - 1 - 2, NG - 1, после выполнения второго — N1 - 2, N2 - 4, ..., NG - 1 - 4, NG - 2 и т.д. Этот процесс продолжается до тех пор, пока одна из групп не исчезнет, после этого ее соседние группы могут объединиться, если они одного цвета.

Это наблюдение позволяет симулировать несколько действий за одну итерацию:

  1. Найти количество действий, необходимых для того, чтобы хотя бы одна группа исчезла.

  2. Пересчитать размеры групп после этого количества действий.

  3. Удалить пустые группы.

  4. Объединить соседние группы одного цвета.

Такая итерация требует O(G) времени и удаляет O(G) точек (не менее одной точки из каждой из G групп). Если начальное количество точек было N, мы можем удалить не более N точек. Таким образом, сложность этого решения — O(N).

909E - Сопроцессор

Действовать следует жадно: пока есть задачи, которые могут быть выполнены на главном процессоре сейчас (т.е. все задачи, от которых они зависят, уже выполнены), их следует выполнять; затем следует переключиться на сопроцессор и выполнять все задачи, которые могут быть выполнены на нем; затем переключиться обратно на главный процессор и т.д. Это можно сделать при помощи аккуратно реализованного поиска в ширину. Один из вариантов реализации — вместо того, чтобы на каждом шаге искать доступные задачи, их следует хранить в двух очередях (задачи, доступные главному процессору и сопроцессору) и добавлять задачу в соответствующую очередь, как только все задачи, от которых она зависит, выполнены.

Существует также более формальное решение. Определим Ti как минимальное количество вызовов сопроцессора, необходимое для выполнения i-ой задачи, и выведем рекуррентное соотношение для Ti. Если u — задачи и v1, ..., vk — ее зависимости, очевидно для каждого i Tu ≥ Tvi (потому что u должна выполняться после vi). Затем, если vi выполняется на главном процессоре, а u — на сопроцессоре, то выполнение u потребует дополнительного вызова сопроцессора. Таким образом, Tu = maxi(Tvi + si), где si = 1, если u выполняется на сопроцессоре и vi — на главном процессоре; иначе, si = 0. Теперь все Ti можно вычислить при помощи рекурсивного обхода графа зависимостей (или обхода задач в топологическом порядке). Ответ — max Ti.

909F - И-перестановки

Перестановка p (pi & i = 0)

Если N нечетно, ответ NO. Действительно, любое число в позиции с нечетным номером i pi должно быть четно (в противном случае последний бит pi&i равен 1). Для нечетных N четных чисел меньше, чем позиций с нечетным номером, поэтому в какой-то из позиций окажется нечетное число, следовательно, сконструировать нужную перестановку невозможно.

Если N четно, ответ YES. Чтобы построить нужную перестановку, заметим, что (2k - i)&(2k + i - 1) = 0. Например, для k = 5:

100000 = 25

011111 = 25 - 1

100001 = 25 + 1

011110 = 25 - 2

и так далее.

Мы можем использовать это наблюдение, чтобы составлять пары из чисел 2k - i и 2k + i - 1, то есть выбирать p2k - i = 2k + i - 1 и p2k + i - 1 = 2k - i.

Полная процедура построения нужной перестановки следующая. Для заданного четного N, найдем максимальную степень двойки, не превышающую N, 2k. Составим пары из чисел 2k - i и 2k + i - 1 для всех i = 1..N - 2k + 1. Если после этого остались еще неиспользованные числа, это будут числа от 1 до 2k - (N - 2k + 1) - 1 = 2k + 1 - N - 2. Повторим процесс для N' = 2k + 1 - N - 2.

Рассмотрим процесс на примере N = 18. На первом шаге мы выбираем 2k = 16 и составляем пары из чисел 15-16, 14-17 и 13-18. На втором шаге неиспользованными остаются числа от 1 до 12, мы выбираем 2k = 8 и составляем пары 7-8, 6-9, 5-10, 4-11 и 3-12. На третьем и последнем шаге неиспользованными остаются числа 1 и 2, мы выбираем 2k = 2 и составляем пару из чисел 1 и 2. После этого все числа использованы, и перестановка построена.

Перестановка q (qi & i ≠ 0)

Для N = 1..7 мы можем рассмотреть все перестановки вручную и выяснить, что для N = 1..5 ответ NO, для N = 6 возможная перестановка \textbf{3 6 2 5 1 4} (из примера в условии), и для N = 7 возможная перестановка \textbf{7 3 6 5 1 2 4}.

Если N — степень двойки, ее двоичное представление 10..0. По условию qN ≠ N, поээтому qN < N, и двоичное представление qN короче, чем двоичное представление N. Следовательно, qN&N = 0, и ответ в этом случае NO.

Наконец, если N > 7 и N — не степень двойки, нужная перестановка всегда существует, и ее можно построить следующим образом. Разобьем все числа от 1 до N на следующие группы (k — наибольшая степень двойки, которая все еще меньше N):

1..7

8..15

16..31

\ldots

2k - 1..2k - 1

2k..N

Для первой группы используем перестановку, которую мы нашли вручную для N = 7. Для остальных групп используем произвольную перестановку чисел в этой группе (например, циклическую перестановку). Числа в каждой группе, кроме первой, имеют общий ненулевой бит в одной и той же позиции (соответствующей степени двойки, с которой начинается группа) поэтому qi&i гарантированно имеет ненулевой бит в этой же позиции.

Разбор задач Codeforces Round 455 (Div. 2)
  • Проголосовать: нравится
  • +125
  • Проголосовать: не нравится

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

Woaaaaahhhh..Lightning fast editorial. Amazing. :)

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

    This is the first contest ever in which I wrote editorials together with the problems, so they were ready even before the start of the round :-)

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

      I always wonder that why all the problem setters don't do it this way in every contest?

      I mean.. it will be so nice for both the parties. Not only we (the noob coders) will get editorials instantly but it might help the setter sometimes to get to know a mistake (if there is in a problem) while writing its solution. This will reduce the chances of a round getting unrated.

      Anyways..you have done a great job.. One of the best contests on codeforces. Congrats for this. :)

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

      Hi, can you provide code for problem D , it looks like a lengthy implementation , the algorithm was not very hard to come up with, also , love the B problem , felt it was a O(1) problem and I was not disappointed :)

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

As always, solution for a problem is quite easy but why I can't come up with it..

Anyway, thanks for great problems!

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

Really interesting problems, thanks! I wish I could solve the F, the solution was near but my brain was making circles around it so I didn't reach it.

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

Greedy simulation for problem B got AC

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

Did anyone solve D by another method : making a right arrays which stores the logical next element and making a left array which stores the logical previous element in array and then performing logical deletion by changing the left and right array values. Eg. _ a a b b_ _ left[i] {-1 , 0 , 1 , 2} ........._ _ right[i]{ 1, 2, 3, 4}_ .................... after one operation , left[i] becomes {-1,X,X,0} and right[i] becomes {3,X,X,4} and so on (by proper implementation procedure taking case of indices etc) and then count total number of steps(again proper implementation required). If anyone solved like this , please provide your code .

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

Thanks for the nice problems. Can you help me why recursive top down solution is failing on time on this solution?Link Is the constant time factor of creating recursion stacks that much?

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

    well , time limit is a little strict honestly (not saying badly formed) , on top of that you are using java + recursion.. also memory is also O(n*n) which I think slows it down a bit more... It would have been better if n <= 3000 , the problem would still remain the same but some failed solutions would have passed ,

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

    You have O(N2) dp states, and for one state you are doing O(N) operations here:

    } else {
                    for (int i = 0; i <= level; i++) {
                        if (dp[index + 1][i] != -1) {
                            ans += dp[index + 1][i];
                        } else {
                            ans += recur(index + 1, i);
                        }
                    }
                }
    

    That makes your solution O(N3), so no surprise it is TL.

    You have to get rid of that bad cycle and use prefix sums to get the value in O(1).

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

Thanks for providing editorial right after the contest!

I was hoping to find some magical connection between two unrelated subproblems from F at least here, but it seems that there is indeed no connection :)

Something quite similar to (A&B==0) subproblem appeared as a problem at CF in past: 288C - Polo the Penguin and XOR operation. Today I got a construction algorithm which sounds a bit different from editorial (I didn't check, maybe it gives same permutations as one from the editorial and I just approached it from the other end). Here is the code: 33686199, function run_solver_false is what we are looking for :) And below I'll try to give some explanation on what's going on there.

Let's take a permutation 2 1 4 3 6 5 8 7 10 9... first, to resolve last bit and p[i]!=i statement. Now let's fix bits one by one from lower to higher. In order to fix a bit X, let's take all positions for which this bit is broken and make a swap of p[i] and p[i-(1<<X)]. We know that (i-(1<<X)) will have 0 at position X, so we are not going to break stuff at that position — but we are still afraid that the number we'll get from p[i-(1<<X)] has 1 at position X as well.

One can check that it is not the case: in each block of size (1<<X) which we consider as a candidate for making a fix there is exactly one number with bad bit, and this number will always stay at second to last position in the block — we will put it there when constructing our base permutation, and then when considering a move at level X (which can possibly affect this number) number in the block to the right will be OK — it will be "bad number" of level X+1. For example: the only moment we can move 4 from position 3 is when trying to fix position 7, but we know that there will be 8 there and it will not need a fix. Generalizing it, the only bad number in block ends with 1000...00 (X times 0), and it will stay at place because the number ending with 1000...00 (X+1 times 0) to the right from it will not need a fix.

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

Could someone explain the solution to problem C. What is the dp array actually storing?

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

    dp array is storing the ways in which a level of indentation can be reached at the n-th instruction.

    for example, lets start with the first line, the indentation level has to be lowest so the array will look like

    1 0 0 0 0 ... 0 (n-1 times 0)

    if it is a for instruction the possible indentation levels when the next instruction is received can only be '1' tab or '1' space. so the indentation can only be equal to '1', ie.

    0 1 0 0 0 0 0 ... 0 ( n — 2 times 0 )

    and similarly

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

      and what is the logic behind other dp states??

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

        Any dp[i][j] represents the ways in which the program can be written with the first i+1 instructions with last line having indentation level of j.

        This holds for i = 0 Since the indentation can only be zero on the first line in one way.

        This holds for any i by inductive reasoning. (You can verify this from the algorithm in the editorial. slycelote has also suggested a correction, please take it into account too)

        So it holds at the n-th instruction. So dp[n-1][j] represents ways of writing the program with first n instructions with indentation equal to j.

        As the indentation can vary from 0 to n we must add up all the terms do[n-1][j] as the program can end with any indentation level.

        Hope this explained the problem

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

        I wrote a blog for you click here

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

          Sir, thank you for this excellent article. Without you I would not have been able to understand the solution of this problem

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

can someone prove that the lower bound we find in problem B is really the smallest number of layers ?

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

    Well for the lower bound to be the smallest number we would need to prove that we can construct each layer such that each segment that covers the maximally covered area [i,i+1] is a part of each layer.

    First off, note that the maximally covered segment is in the middle as a segment [i,i+1] is covered by (i+1)*(n-i) segments (taking one starting point <=i and ending point >=i+1). (There are two such areas when n is even)

    Then we can construct a solution: starting from i=0 take any segment starting at i, and ending at n-i, and split that segment at some point. One of the segments will cover the maximally covered area. Repeat this for all such split points. increment i, repeat.

    It is clear that every layer includes a unique segment that covers the maximally covered area, and every segment is included in one layer. Thus, as every layer includes a unique segment that covers the maximally covered area, the number of layers is the same as the number of unique segments that cover the maximal area, aka the lower bound. So the lower bound is the smallest number of layers.

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

    If you think of the construction procedure in the editorial, you'll realize that the only time we add a new layer is when current segment [i, i + 1] is occupied in each of the existing layers. And that's exactly what the lower bound argument used.

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

An Elegant Sol to B :

      int n = i();
      int cnt[] = new int[n + 5];

      for(int i = 1; i <= n + 1; i++){
        for(int j = i + 1; j <= n + 1; j++){
          cnt[i] += 1;
          cnt[j] -= 1;
        }
      }
      long ans = 0;
      long sum = 0;
      for(int i = 1; i <= n + 1; i++){
        sum += cnt[i];
        ans = Math.max(ans, sum);
      }
      out.write(""+ans+"\n");

Ref

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

B — Segment in Haskell

ff 1 = 1
ff 2 = 2
ff x = x + ff (x-2)
main = do
    g <- getLine
    let x = read g :: Int
    print $ (ff x)

`

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

    In Java

    public class v2 {
    	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    	public static void main(String[] args) throws Exception {
    		int n=Integer.parseInt(in.readLine())+1;
    		System.out.println(n*n/4);
    	}
    }
    
»
7 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

In C how time complexity is O(N*N)?

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

    U can use prefix sum to calculate the summation instead, hence reducing the complexity from O(n*n*n) to O(n*n).

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

In problem (C — Python Indentation) output for the following input is 23. But how? I don't get it.

input:
8
f
s
f
f
s
f
s
s
Correct output:
23

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

    Задача С. Пронумеруем позиции в строке слева направо и будем в массиве А хранить количество вариантов программы, начинающихся на данном шаге написания программы с данной позиции. Рассмотрим очередной шаг написания программы. Если предыдущая команда "f", то следующая команда пишется со сдвигом на одну позицию вправо, т.е. количество вариантов, в которых последняя строка начинается в позиции 1 равно нулю, в позиции 2 — равно числу вариантов в позиции 1 на предыдущем шаге, в позиции 3 — в позиции 2 и т.д. Для всех i имеем A[i]:=A[i-1]. Если предыдущая команда "s", то следующая команда пишется либо в ту же позицию, либо в ЛЮБУЮ позицию левее, т.е. в данном случае для всех i A[i]:=A[i]+A[i+1]+A[i+2]+ ... и т.д. до последней возможной позиции начала первой строки на предыдущем шаге. После выполнения всех шагов написания программы нужно найти сумму вариантов для всех позиций начала последней строки. После написания первой строки A[1]=1, все остальные члены массива равны нулю. Далее N-1 раз повторяем описанный алгоритм нахождения числа вариантов начала последней строки в каждой из позиций. При чтении условия возникает впечатление, что соседние строки не могут начинаться с позиций, номера которых отличаются на количество отступов больше одного, т.к. в тексте задачи явно не сказано, что после завершения цикла следующая инструкция может начинаться с любой позиции с меньшим количеством отступов. К сожалению, приведённые примеры не позволяют избавится от такого заблуждения.

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

    You can use this test case to debug your code:

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

In problem C, in the first input testcase given, the dp matrix formed by the given editorial will be : 1 0 0 0 1 1 1 1 0 1 1 1 0 0 1 1 and the final answer will be 2 but the answer in this case is 1. Can you please explain what am I missing here. Link to my code

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

    Looks like the editorial has a typo, the actual recurrent formula is .

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

      slycelote Thank you for correcting the typo. Please also provide some details about how we derived this recurrence if ith command is a simple statement.

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

        As pointed out in the editorial, indentation of the command following the simple statement must be less than or equal to indentation of the simple statement. In the formula above, k is indentation of the simple statement, j is indentation of the next statement, and we sum over all k such as j ≤ k.

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

        [user:sukhbhir947] Lets say you put the i+1th command with indentation k, then the ith command can only be with indetation k or k+1 or k+2 or .... n. So the number of ways of putting the command i+1 with indentation k will the sum of all the ways you can put the ith command with indentation k, k+1, k+2 ... n.

        Hope it helps!

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

      Thanks a lot!

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

Hello all, I need some help in understanding problem C's editorial. If ith command in the program is a simple statement then how did we derived the recurrence relation for i+1 th command.

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

    if ith one is simple then no matter what is the current command we can indent it in any of the statements before the last indentation of ith command(maximum indent).

    see if fffs then we are about to add f. As the maximum indentation of previous command (i.e. s) is 4 so, we can put the current f in any of the for loops or with that s!

    Hope it helps.

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

for DIV-D : i didn't understand the time complexity part. We have G groups and at each step we remove 1 group and then update the remaining one. so, updating takes O(G-1) time (if we do linearly). so, complexity will be about O(G^2) ! I think that the size of groups reduces at each step and possibly that is the point i am missing. But can someone please provide any mathematical stuffs. will be a great help! :)

AND thanks for such a nice tutorial happy new year :)

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

    Time complexity will be the sum of O(G) over all operations. At the same time, the total number of points removed will be at least the sum of G over all operations because for each operation we remove at least one point from each group. We cannot remove more than N points in total, so this sum is not more than N, and the sum of O(G) is not more than O(N).

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

Hey all Can someone please tell me the detailed solution of problem C (Python Indentation) I approached the question as a)if there are two 'for' statements (not consecutively) the total number of possibilities get multiplied by 2
b)if there are n 'simple' statements(consecutively) inside a 'for' loop then total number of possibilities increase by n-1 Please tell me my blunders in my approach.

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

can someone please explain the second approach mentioned in the editorial of E.

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

For Problem C Python indentation why is the final answer the sum of (j takes on all levels) dp[n-1][j],and where is the running variable k in the summation used?.(k=0 to N-1) Thanks!.

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

    This is another typo. Sum is over all possible indents of the last command k, and dp[N - 1][k] is the number of programs which end with command N - 1 at indent k.

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

In the tutorial of the 909C-Python Indentation it's given that: "If command i is a simple statement, command i + 1 can belong to the body of any loop before it, and have any indent from 0 to the indent of command i:" But then the formula sums from i=j to n. Shouldn't it be from 0 to j?

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

    If command i is a simple statement, indentation of command i + 1 must be less than or equal to indentation of command i. In the formula, k is indentation of command i + 1, j is indentation of command i + 1, and we sum over all k for which j ≤ k — this requires summing upwards from j, not downwards.

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

There is a slightly slower solution to D that will AC.

It is essentially an optimized simulation; we don't need to check the neighbors of every point, only the points that get new neighbors. Which are the points that get new neighbors? Well, these are just the points adjacent to the removed points (be careful not to mark a removed point as having a new neighbor).

We'll keep three sets: one with all the points, one with the points that have new neighbors (we'll actually need a current and a next for this set, and then use pointer swapping, but it's easy to think of it as just one set), and one with the points you are going to remove. On each iteration of the simulation, check if the points with new neighbors need to be removed, and add them to the remove set. Then, add their neighbors to the "has new neighbors" set. When you iterate over the "remove" set, just make sure you delete any of those elements from the "has new neighbors" set.

Each element can be removed at most O(1) times, and each of its neighbors will be added to the "has new neighbors" set, so there are at most n insertions to that set, and of course n deletions as well, so the amortized complexity is O(n logn).

Your solution is definitely easier to implement, but I think in some cases this might be easier to think of.

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

Can someone explain for Problem D:

Answer for input: bccdeefggiaacndddd

should be 2.

But according to solutions it is : 1

My solution for 2 is : (bc)(cd)(e(ef)g)(gi)(a(ac)n)dddd

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

    Why should it be 2? Each point, except for the last 3 "d"s, has a neighbor of a different color and thus will be removed during the first operation; after that the points will be "ddd" and none of them have a neighbor of a different color, so second operation can't be done. Points do not have to be paired up to be removed

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

Here's an alternate construction for the second part of F. Assume we want a solution for some value of n that is greater than 6 and not a power of two.

If we have a solution for n - 1. We just find a power of 2 say 2p less than n such that n contains a 2p in its binary representation. Then we construct a solution for n by assigning the 2p in our previous solution a value of n and n the value that 2p had before the reassignment. We leave everything else the same.

Next if we don't have a solution for n - 1, but we do have a solution for n - 2 (i.e in the the case n - 1 is a power of 2). We just take our solution for n - 2 and put {n, n - 1} on the end and we have a solution for n.

Then we just use this process to construct a solution using the solution for n = 6 in the example.

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

For problem D , I use the set to maintain the remaining indexes which can be operate,but i got TLE on test 5. (:

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

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

I have a slightly different solution to problem D.

After making groups, we can observe that the simulation process cannot take more than $$$sqrt(n)$$$ "steps", because at each "step", we remove all values with equal ceiling function divided by two value, and the number of edge removals are bounded above by $$$logn$$$ "steps", so the overall complexity is $$$O(n(sqrt(n)+log(n))$$$ which is around $$$7*10^8$$$ operations for $$$n==10^6$$$, which passes in $$$33$$$ milliseconds.