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

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

DivII A. Печеньки

Самый лёгкий способ решить задачу — сперва посчитать всю сумму чисел, и затем посчитать количество чётных разностей между этой суммой и каждым числом. Однако маленькое наблюдение позволит написать решение немного эффективней: помимо суммы (sum) посчитаем также, сколько среди данных чисел есть чётных (even) и нечётных (odd). Тогда, если сумма нечётна, то ответ — odd, иначе — even. Время O(n), память O(1).

DivII B. Шнурки и шестиклассники

Маленькие ограничения позволяют нам написать решение «в лоб». Будем хранить данный граф в матрице смежности, и симулировать происходящее. Также будем хранить степень каждой вершины отдельно, чтобы быстро находить детей, которые связаны только одним шнурком. Тогда при каждой итерации удаляем все вершины со степенью 1 и все грани, которые соединяются с этими вершинами; продолжаем до тех пор, пока не останется таких вершин. Ответом будет количество произведённых итераций. Время O(n3), память O(n2).

DivII C / DivI A. Статуи

Произведём симуляцию падения статуй. При каждой итерации будем сдвигать все статуи на одну клетку вниз. Перед каждым ходом (итерацией) будем получать список всех полей, куда Маша может пойти (до того, как статуи передвинутся на одну клетку вниз), используя список тех полей, куда она могла придти с прошлого хода (единственное, из полей с прошлого хода можно использовать только те, в которые после конца прошлого хода не переместилась статуя). Логично, что через 8 любых ходов на доске не останется ни одной статуи. Поэтому, если список  доступных Маше полей после 8-ого хода не пуст, то она может добраться до Ани, потому что дальше её ходы ничто не ограничивает. Время O(9· 83) = O(1), память O(82) = O(1).

DivII D / DivI B. Строка

Вначале ликвидируем случай невозможности — такой строки нет, если k больше, чем количество подстрок, т.е. , где n — длина строки.

Теперь заметим, что для каждой буквы мы можем быстро оценить, сколько подстрок начинаются именно с этой буквы. Действительно, если буква стоит на позиции i (нумеруя с 1), то количеством подстрок, начинающихся с позиции i, является n - i + 1. Тогда количество строк, которые начинаются с конкретной буквы, будет сумма всех таких значений для позиций, в которых стоит эта буква.

Далее, используя найденную информацию, не сложно выяснить, с какой буквы будет начинаться нужная подстрока (потому что в слове при лексикографическом сравнении буквы слева важнее, чем буквы справа). Теперь заметим, что тоже самое рассуждение мы можем применить и для следующей буквы нужного слова, только теперь нужно проверить только такие буквы, которые следуют после первой буквы слова. Таким образом, мы повторяем итерации и для 3-ей, 4-ой, ... букв до тех пор, пока не найдём нужную строку. Чтобы не искать каждый раз нужные позиции, будем хранить их отдельно; при каждой итерации сдвигать их на одну позицию направо и исполнять алгоритм только для них, а после нахождения i-того символа убирать те позиции, буквы в которых не равны с найденным символом. Время благодаря k ≤ 105 не квадратичное (самому ещё не получилось доказать), память O(n).

Также задачу можно было решить с помощью хэшей или суффиксного массива.

DivII E / DivI C. Игра с прямоугольниками

Рассмотрим все левые и правые границы всех k внутренних прямоугольников, вместе их 2k. Присвоим им произвольные 2k координат между левой и правой стороной данного прямоугольника, это можно сделать способами. То же самое сделаем и с верхними и нижними границами, это можно сделать способами. Заметим, что каждая пара таких размещений однозначно определяет одно искомое расположение, и все такие расположения можно определить одной парой размещений. Поэтому ответом является . Так как n и m не больше 1000, то коэффициенты можно посчитать с помощью треугольника Паскаля (не забывая вычислять по данному модулю). Время O(max(n, m)2), память O(max(n, m)2).

DivI D. Числа

У меня эта задача ассоциировалась с атомами и молекулами. :) Представим, что каждое из чисел имеет две связи, где связь соединяется с другой по заданным правилам. Тогда решение существует тогда и только тогда, когда все связи соединены, и из каждого элемента по связям можно дойти до любого другого элемента; также решения не существует, если присутствуют числа x, x + 2, но x + 1 не присутствует.

Пусть у нас есть числа a, a + 1, ..., b, тогда количество связей у них 2|a|, 2|a + 1|, ..., 2|b|, где |x| — количество чисел x. Ясно, что 2|a| связей от 2|a + 1| «съедают» элементы a. У a + 1 свободными остаются p = 2|a + 1| - 2|a| связей. Аналогично, эти p связей соединяются с a + 2 элементами и т.д. В конце концов, если у b - 1 свободными остаются q связей, то должно быть q = 2|b|, чтобы завершить цепочку. Остаётся только проверить все эти соотношения (учитывая то, что цепочку нельзя завершить раньше, чем не истрачены все связи — то есть, вычисляемый p не может быть 0). Время (т.к. данные числа нужно отсортировать), память O(n). Для простоты вычислений можно ещё заметить, что 2|a| можно заменить на |a|, из-за этого ничего не изменится.

DivI E. День рождения

См. хороший разбор здесь.

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

12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
У вас в задаче С для Див 2, написано, что ходит Аня, хотя это не верно.

Я не понимаю ваше решение (и как получилось время O(1), если у вас есть какие-то итерации). Предлагаю свое, как альтернативу вашему, так оно для понимания проще.

Заводим массив a[x][y][t]. Где x, y - координаты клетки, а t - момент времени. С увеличением времени у нас происходит перемещение фигур вниз на одну клетку, так что мы знаем где стоят статуи в каждый момент времени. Получается, что при t == 0 у нас хранится карта из входных данных, а в t == 8 хранится пустая карта (заполнена точками). Теперь нам просто нужно написать обход графа, учитывая, что подняться на уровень t + 1 мы может только в ту клетку, в которой нет статуй как в момент времени t + 1, так и в t. Ответ "WIN" если попали в любую точку пустой карты (t == 8), потому что из нее достижимы все точки, включая ту, которая нам нужна.
  • 12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Перепутал имена, исправлено :) А O(1) выходит из того, что доска константного размера 8 × 8, и итераций не больше 8.

    • 12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      при этом из каждого состояния у Вас 9 переходов. Я согласен, что 640  * 9 - это очень мало, но тем не менее, это не О(1).
      • 12 лет назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится
        Ну, если у нас в любом случае количество операций ограничено сверху какой-то константой — это как раз и есть, по-моему, константная асимптотика.
        • 12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          С той же точки зрения можно сказать, что O( n ^ 3) при n <= 10 ^ 6 ограничено сверху 10  ^ 19, а 10  ^ 19 - это константа, следовательно является константной асимптотикой.
          • 12 лет назад, # ^ |
              Проголосовать: нравится +3 Проголосовать: не нравится
            Нельзя, если n переменная величина, а при оценке асимптотики ограничения на переменные величины не учитываются.
            • 12 лет назад, # ^ |
                Проголосовать: нравится +1 Проголосовать: не нравится
              имхо бред. Тогда лучше писать примерное кол-во операций, а то если нужно что-то сделать на отрезке от 1 до 1000000000, то это тоже будет О(1)? И что эта оценка будет говорить?
              • 12 лет назад, # ^ |
                Rev. 2   Проголосовать: нравится +11 Проголосовать: не нравится

                В таком случае лучше написать O(9· 83); обновлено.

12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
     Ну, если уж пошла такая формалистика, то внесу свою лепту.  В задаче D div 1 сортировка вовсе не обязательна.  Можно просто проверить, что max-min<=n/2, а затем сразу переходить к массиву частот - тогда решение будет чисто линейным.  
»
5 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Here is my code for "Students and Shoelaces" problem, please let me know if I can optimize it in someway...

#include <bits/stdc++.h>

using namespace std;
const int MAX = 10000;

vector<int> graph[MAX];
int degree[MAX] = {0};

int n, m;
int main(){
    cin>>n>>m;
	for(int i = 0; i < m; i++){
	    int a1, a2;
	    cin>>a1>>a2;
	    graph[a1].push_back(a2);
     	    graph[a2].push_back(a1);
	    degree[a1]++;
	    degree[a2]++;
	}
	queue<int> q;
	for(int i = 1; i <= n; i++){
	    if(degree[i] == 1)
		q.push(i);
	}
	if(q.empty()){
	    cout<<0<<endl;
	    return 0;
	}
	int ans = 0;
	while(!q.empty()){	
	    queue<int> q2;
            while(!q.empty()){
		int front = q.front();
		q.pop();
		for(auto ne:graph[front]){
		    degree[ne]--;
		    if(degree[ne] == 1)
			q2.push(ne);
		}
	    }
	    ans++;
	    int size = q2.size();
  	    for(int i = 0; i < size; i++){
		if(degree[q2.front()] == 1){
                    q.push(q2.front());
		    q2.pop();
		}
		else
  		    q2.pop();
	    }
	}
	cout<<ans<<endl;
}
  • »
    »
    4 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    You should put the code into the Spoiler
  • »
    »
    4 года назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
    Here if you need
    If you still want the queue

    My submissions

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

Could you help me explain why the time complexity in problem C (div 2) is O(9.8^3)

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

I am having difficulty in finding the solution for the "Students and Shoelaces" solution because the output the of the Codeforces compiler for Testcase#3 is different from the output my offline text editor (Sublime Text) is giving (my text editor is giving the right answer whereas the codeforces compiler is giving a wrong answer). The Codeforces compiler is also giving a error message for this testcase : Diagnostics detected issues [cpp.clang++-diagnose]: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\include\vector:1802:11: runtime error: addition of unsigned offset to 0x12b01340 overflowed to 0x08a60930 SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\include\vector:1802:11 in ``

So I read that this error message is given when there is some out of bound cases. To fix that I modified the code but that modification is giving me wrong answer for Testcase#51.

My initial submission : https://codeforces.com/contest/129/submission/78633028

My modified submission : https://codeforces.com/contest/129/submission/78634662

Is there something wrong with my logic or my code? How can I fix it?

Thank you for your time.

PS : Here is a short explanation of my code : adj[i] is a map of all the students connected to the ith student. mp[i] is used to store students with i number of connections. Therefore mp[1] stores the students which have 1 connection. The while loop simulates the entire process. The vector v stores the students which will be having 1 connection in the next round i.e. if a student had 2 connections and one of the connected student got kicked in round i then the number of connections reduces to 1 connection, which means that this student will have to reprimanded in round i + 1. The run variable checks if the current group of students have already been counted; hence when the new round of students with 1 connection is considered, the run is reset to false

UPD : Problem fixed — I had to change my approach as it was not covering many corner cases. I used a queue to simulate the process. Here is a link to the solution : 83548603