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

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

Всем привет.

Автором задач сегодняшнего раунда являюсь я. Раунд будет проходить в двух дивизионах. В каждом дивизионе будет предложено по пять задач.  Это мой второй раунд на Codeforces. Персонажами в задачах, как и на прошлом раунде, будут моржи =)

По традиции выражаю огромную благодарность команде Codeforces и Alias за помощь в подготовке контеста.

Желаю всем успеха и пусть победит сильнейший!

UPD1:

Разбаловка задач для div1: 500-1000-1500-2500-2500

Разбаловка задач для div2: 500-1000-1500-2000-2500

UPD2:

Победитель в div1: SergeiRogulenko
Победитель в div2: piotr.mikulski
Мои поздравления!

Разбор

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

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

Ну и небольшая шутка юмора в в виде бонуса-картинки =)

15 лет назад, скрыть # |
 
Проголосовать: нравится -21 Проголосовать: не нравится
А, кстати, почему именно моржи? Чем Вам так понравились эти животные?
15 лет назад, скрыть # |
 
Проголосовать: нравится +2 Проголосовать: не нравится
Блин я сейчас на даче с модемным интернетом который не всегда ловит. Даже не знаю писать или нет
15 лет назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится
There is, in total,10 problems? Or is it 7 problems with the regular style -> (1 2 (3 4 5) 6 7)?
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +14 Проголосовать: не нравится

Codeforces Beta Round #64
By Connector3 months ago
if you wan't to see the problems by the same auther click here

15 лет назад, скрыть # |
 
Проголосовать: нравится -8 Проголосовать: не нравится
желаю удачи всем участникам!
15 лет назад, скрыть # |
 
Проголосовать: нравится -6 Проголосовать: не нравится
Как заблокировать задачу?
15 лет назад, скрыть # |
 
Проголосовать: нравится +31 Проголосовать: не нравится
Сегодня были очень интересные и разносторонние задачи. Спасибо автору
15 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится
Как решалась С, расскажите?
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Если учитывать пустую лыжную базу, то число вариантов - 2^число ребер добавленных между уже связными вершинами. А так единичку еще вычесть надо
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +6 Проголосовать: не нравится
    Это баян с какого-то старого топкодера, а может, и более древний. Количество обобщённых циклов равно 2^размерность циклового пространства, которая в свою очередь равна m - n + k, где n - число вершин, m - число рёбер, k - число компонент связности.
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +5 Проголосовать: не нравится
    Надо понять, что циклические множества (= трассы включая пустое множество) образуют линейное подпространство (над F2), а размерность его в случае связного графа G(V, E) равна |E| - (|V| - 1): для этого надо понять, что можно выбрать в качестве базиса. Зафиксируем некоторое остовное дерево, утверждается что базис образуют циклы, образуемые некоторым оставшимся ребром и некоторыми ребрами дерева.
    Т.е. мы знаем в случае связного графа, что ответ равен 2|E| - (|V| - 1) - 1, на несвязный все просто обобщается.

  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Кстати, увидев там явно неквадратичные ограничения и конструирование графа в онлайне, я, учитывая личность автора (точнее, задачу C с его предыдущего раунда), ожидал, что решение - какая-то адовая жесть с модификацией алгоритма Тарьяна. И опять моя предвзятость не оправдалась, как и с A.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Сегодняшняя задача B (в первом дивизионе) один из редких случаев, когда STL заруливает дот-нет. Точно знал, как что у дот-нетовских коллекций типа std::map нету lower_bound и upper_bound для поиска ближайшего. Решил, что ну и фиг с ним, напишу на сях++. Оказалось, что и в сях++ не знаю как оно работает, пришлось по ходу дела маны читать, экспериментировать. Кое-как родил что-то кривое. Оно потом ещё и на закомпилировалось системой: оказывается для метода std::reverse надо подключать <algorithm>, в том stl, что с 2010-й студей достаточно было <vector>, а остальные сопутствующие где-то внутрях автоматом подхватываются.
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +10 Проголосовать: не нравится

Автору  воздастся - я проиграл ему кружку пива, что же вы так мало E сдавали? Я считал что её будут лучше сдавать чем C.
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Не знаю. У меня небанальный тернарный поиск внутри дерева интервалов...
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    У меня было довольно техничное решение с деревом отрезков, в каждой вершине которого я хранил вектор отрезков времен доминирования. Сливал такие вектора за линию. Быстро такое писать не умею, писал минут 45. Есть решение сильно проще?
    • 15 лет назад, скрыть # ^ |
      Rev. 2  
      Проголосовать: нравится +8 Проголосовать: не нравится

      У меня просто дерево интервалов, в котором мы еще знаем когда информация в поддереве устареет т.е. доминировать начнет что-то другое. Реализация у E сложнее, но идейно она проще на мой взгляд. У неё есть множество решений, а в C нужно врубиться про компоненты связности.

      UPD: сортируем запросы по времени, каждая башенка со временем может подыматься в дереве двигаясь к корню (к вершине 1) обгоняя другие башенки, и становясь лидером на все больших интервалах. Каждая башенка может подняться не более LogN раз, надо просто придумать как обновлять дерево так, чтобы выполнить всего не более  NLogN операций
    • 15 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится
      Это одно из авторских решений. Оно требует O(n log n) памяти. Можно было использовать sqrt декомпозицию. Она работает быстрее из за меньший размер памяти O(n) и меньше беготни по памяти.
15 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

За полчаса до конца контеста был вынужден выйти, теперь не могу даже зайти в соревнование. Поправьте, пожалуйста.
15 лет назад, скрыть # |
 
Проголосовать: нравится +23 Проголосовать: не нравится
Could you please start system testing?
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Наконец нашел баг в своем решении Д. Ждем дорешивания.
15 лет назад, скрыть # |
 
Проголосовать: нравится +10 Проголосовать: не нравится
Михаил Расихович, а согласно какой логике сначала проверяется второй дивизион, а только потом первый?
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +38 Проголосовать: не нравится

The statements are easy to understand, I like this :d.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Div2 Problem C: system test is weak?
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится -15 Проголосовать: не нравится

Ребят, я дебил, как А решать? :-D
  • 15 лет назад, скрыть # ^ |
    Rev. 4  
    Проголосовать: нравится 0 Проголосовать: не нравится

    Хранишь для каждого символа, места где он встречается, потом перебираешь s2, ищешь следующий s2[i] символ после текущего места, если его нет, то увеличиваешь ответ и ищешь сначала.

    UPD: ищешь бинпоиском конечно, а не за линию. итого |s2|*log |s1|

    UPD2: С прямыми руками заходит
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Я для каждой буквы для каждой позиции первого слова посчитал позицию первой следующей после нее такой буквы... А дальше просто "прыгал" по массиву, сохраняя текущий ответ и позицию. Если после данной позиции нужной нам буквы больше нету, то возвращаемся к началу слова (и +1 к ответу - "приписали слово еще раз").

    А то, можно ли записать, проверяем просто - все ли буквы второго слова есть в первом.

  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Запомним для каждого символа из первой строки позиции, в которых он встречался. будем поддерживать текущую позицию pos в первой строке и идти указателем по символам второй. если окажется, что какой-то символ s2 не встречался в s1, то выводим -1.
    иначе, для массива позиций символа ищем первый, который идет после pos. если такого нету, то увеличиваем счетчик ответа, и pos присваем первую позицию, где этот символ встретился. иначе, обновляем pos.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Эх, надо было спать идти. В итоге полу-сонный завалил контест. В A тупой баг и +2, в B вообще решение с деревом отрезков. В C подсознательно всплыло, что ответ должен быть 2^(что-то), но было поздно.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Can any one explain the logic behind Problem D Div2 ? And the order in which it can be solved ? 

15 лет назад, скрыть # |
 
Проголосовать: нравится +38 Проголосовать: не нравится
У меня предложение со следующего раза ввести единую нумерацию задач: A, B, C, D, E для div2 и C, D, E, F, G для div1. А то больно много путаницы получается: не все понимают пока, что div1 B и div2 D, например, одно и то же.
15 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
damn i wrote the code for D  i just clicked submit n time got over :-( bad luck  :-( 
15 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
Ratings got updated for DIV-2 ??

15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +10 Проголосовать: не нравится

Interesting contest.

Kind of guessed the answer in C and was pretty close in D.

I'm waiting for the editorial, especially for the proofs of C and D.
15 лет назад, скрыть # |
 
Проголосовать: нравится +14 Проголосовать: не нравится
Div-1 problem D
bool used[10000]; //on the contest RE 10
bool used[100000]; //after the contest AC


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

I am very suprised.In problem B,div2,I use string always got RE on pretest 2,but I  use char got AC,why??whether it is relative to the head files,I type #include<string.h> and #include <string>

15 лет назад, скрыть # |
 
Проголосовать: нравится +26 Проголосовать: не нравится
I passed problem E with time 4920ms ... Lucky guy I am, right~?
15 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится
Nice Contest and well framed , short and crisp problem statement
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +3 Проголосовать: не нравится

Thanks for the contest! The problems were excellent, varied, the statements were very clear, and I'm very curious about the problems that I didn't solve, which is the way it should be :)

BTW, I thought that more people would implement a brute-force approach in Div1 A (maybe they did in Div2 C). It looked like a good hack target but I only managed to find three slow solutions in my room.

Waiting for the editorial :)

15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Автору: можно как-то узнать тест 16 к Div 2 D полностью? У меня отличается 1360-ое число, которое я не могу увидеть... :(
15 лет назад, скрыть # |
 
Проголосовать: нравится +8 Проголосовать: не нравится
Good contest!

For problem B, I have read the statement twice and ask 2 questions then understand it.
I don't think this statement is so clear, but others is really clear.
 
For problem C, it's a little bit unusual.
But if you know some connections between graph and linear algebra then it will be really easy.

For problem E:
Is someone solved it by divide the people into groups?
1.Prepare: for each group, calc all important time and at that time who is the best.
Cost time O(BA2logA) where A is the amount of people in a group, B is the amount of groups.
2.Query: for the groups by binary search, and combine the left-most and right-most single ones.
Cost time O(Q(B+A)logA).
For A = B = sqrt(Q):
The time complexity is O(N1.5logN).
But I can't pass.


  • 15 лет назад, скрыть # ^ |
    Rev. 4  
    Проголосовать: нравится +8 Проголосовать: не нравится

    I haven't got time to implement the following idea.
    Use offline method to handle queries, the binary search won't be necessary.
    sort all queries by time, and insert them into "groups", for each group, the time is sorted and some linear scanning may work.
    still lots of minor things had to be considered to achieve O(n^1.5) complexity, and this solution may result MLE with a poor implementation.
15 лет назад, скрыть # |
 
Проголосовать: нравится +6 Проголосовать: не нравится
I forgot to use stable_sort and I did not know that I could sort with pairs, or I could pass Div I B in 12 minutes :(
Anyway, learning is always happy:)
15 лет назад, скрыть # |
 
Проголосовать: нравится +32 Проголосовать: не нравится
I think that you should improve hacking interface. It is very slow and sometimes didn't open properly (I had to open some solutions for several times, before I could see the source). Also when I was reading somebody's code I got some strange messsage about reading the solution for too long and the hacking window closed.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Anyone for Div-2 E explanation .... plz
15 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
Только мне кажется что в нескольких последних контестах как-то странно изменяется рейтинг.
Вот например у adry за последнее место в диве 2, рейтинг упал только на 69 пунктов, у durt за последнее место в диве1, рейтинг упал на 70 пунктов. Как-то странно это.
15 лет назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится
Это все из-за того что нету общих контестов где Div. 1 и Div. 2 вместе пишут. И неизвестно когда будет такой. Видимо это теперь вошло в привычку.
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    ИМХО, совсем не из-за этого. Раньше на совмещённых контестах рейтинг считался всё равно отдельно.
    Вот, кажется, основная причина.

    Тему эту уже подняли в прямой эфир.
    • 15 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится
      Ясно. Кстати очень тяжело перейти в див. 1, надо решать побольше чем 2 задачи :)
      • 15 лет назад, скрыть # ^ |
        Rev. 2  
        Проголосовать: нравится 0 Проголосовать: не нравится

        В див. 1 ещё хуже - там часто можно не решить ни одной (учитывая, что первые две простые задачи в первом диве нет).
      • 15 лет назад, скрыть # ^ |
         
        Проголосовать: нравится 0 Проголосовать: не нравится
        Так это весьма логично, особенно если говорить о последнем раунде.
        Ведь Div.2 C в нем совпадала с Div.1 A.
        Т.е. решив только две задачи во втором дивизионе получается что в первом ты бы не решил ни одной? Тогда значит рано тебе туда, ведь заметь, там А решили почти все.
        И вообще, здесь довольно высокий уровень первого дивизиона, кажется повыше чем на топкодере. Да еще и шкала рейтинга сильно растягивается и тяжело прогнозировать куда все это ведет.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Wow, this is a really fun contest! Too bad I missed it :(

Does anyone know when is the next contest?
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
as for the Ski Base,I don't understand the analysis of it,I can't clearly understand why the solution is correct.Can anyone explain to me? Thank you 
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +1 Проголосовать: не нравится
    Every graph with even degree for all of its vertices is a sky base. If you don't know why, then study Eulerian circuits. So we are counting sub-graphs with all vertices having even degree. Consider a spanning tree for each of the components of the graph. All other edges not in the spanning tree have two possibilities for existence. And the existence of edges in the spanning tree is determined uniquely after that. So every time we add an edge to a component the number of even degree sub-graphs is doubled. But when we connect two of the components the answer doesn't change (Why?).
    Hope it helps, sorry for bad English.
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I need clarification for problem E(div 2). Specially i m very much confused about the paragraph

"Let's consider the ski base as a non-empty set of roads that can be divided into one or more tracks so that exactly one track went along each road of the chosen set. Besides, each track can consist only of roads from the chosen set. Ski base doesn't have to be connected."

What is meant by this paragraph......................


15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
I could not understand the editorial of problem C in div 2 and A in div 1 related to newspaper headline and why it is tagged as binary search and how the solution could be implemented as binary search. I doubted on whether somebody will read it or not but just want to say that please provide more explanation in editorials rather than providing few lines, although a problem could be easy for good coders but for beginner it is the ladder, so please don't make it difficult to climb.
  • 15 лет назад, скрыть # ^ |
    Rev. 4  
    Проголосовать: нравится +1 Проголосовать: не нравится

    See Burunduk1's code , it is very clear.
    suppose the target word is abcd
    Then in the source word , first search for a then search for b , but don't start search from start, instead search from the position you last found the matching character that is a in this case.
    Why we are doing this :: Because we don't want to take new headline unnecessarily .
    By checking whether we can find b next-to where we found a , we can save 1 headline-expense. If b is not found next(next does not necessarily mean adjacant) to a . We will have to use another headline. So, then search the source string(that is the headline),from start for b. Doing this again and again will provide you how many headlines you need. But this is SO costly. Every time you will have to search for a character in O(n) time. So, you see, this is very costly , given such constraints. So, we use binary search. We binary search for the next position where the next character to be searched is located. Suppose a was found at 5th   position, now we want to find b, nearer to 5th position but on the right side.
    How do we do this::
    Do pre-processing, store all b's location in a array.
    Then binary search for 6 , if there is position greater than equal to 6 . that should be our next b's position. If no b is found after 5th position ::
    Take new headline. :( 
    Doing this for all characters , will produce the answer.

    • 15 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится
      Thanks for explaining how binary search is implemented in this problem, but I could not understand the portion related to binary search of Burunduk1's code.
      I have added few lines to understand what is going on on test case 2 of the example (abcd,dabc)....
      forn(i, tn)
        {
          vi &v = pos[t[i] - 'a'];  
      // v[3]=3 for 'd'

          int j = lower_bound(all(v), p) - v.begin();
      // can't understand.
      have read about lower_bound.but how p=0 will find 3 in vector
          printf("%d\t%d\n", j,p);  
          if (j >= sz(v))            
            cnt++, p = v[0] + 1;
          else
            p = v[j] + 1;

        }
        printf("%d\n", cnt);

      and I got this as the output:
      0    0
      1    4
      0    1
      0    2
      2
       could you please explain me little bit more as I am unable to correlate the output to the input with the help of code?
      • 15 лет назад, скрыть # ^ |
         
        Проголосовать: нравится 0 Проголосовать: не нравится
        "but how p=0 will find 3 in vector"

        lower_bound finds next integer that is greater than or equal to supplied one. (here 0).
        ---------------------------------------
        if source string is abcd.
        then v for d's case will be {3} since the only d is at 3.
        and lower_bound will return that.


        • 15 лет назад, скрыть # ^ |
           
          Проголосовать: нравится 0 Проголосовать: не нравится
          Thanks for correcting me. Now I still have 2 doubts.
          1. If the target is "dabc" and source is "abcd", then after 'd' p=4, so for target: 'a': v[0]=0; then how p=4 in lower_bound will give j=1?
          2. What I have learned from Top coder algorithm tutorial and recipes is that to use binary search there should be predicate which is true for some interval and false for other interval. so we continuously divide the search space until found the correct one. But in this case we are maintaining separate container for every alphabet in source and storing its position. then we are applying steps you mentioned but how this is binary search? How have we divided the search space?

          Lastly could you refer me more problem like this for practice.
          • 15 лет назад, скрыть # ^ |
             
            Проголосовать: нравится 0 Проголосовать: не нравится
            1. When  'd' is found .
            p becomes 4.
            Then in vector v for 'a'. there is no such 'a' with position >= 4. So, p will now change to 0.[new headline required] (it will not go into if part , it goes to else part.)

            2.See, you got a sorted sequence of numbers. All you required is to find, a number which is "just" greater than or equal to some number say x.
            Take a example instead,
            1,2,3,4,4,5,5,6,7,8.
            can you find 4 using binary search.
            it is pretty simple.
            (I will leave it for you)
            hint:: search in last ,if greater search in-between first and last , if smaller search between....so on and so forth...

            Lastly, there are lots of problem on binary search , here and at topcoder.
            Use Google (and the word "archive")  
            • 15 лет назад, скрыть # ^ |
               
              Проголосовать: нравится +5 Проголосовать: не нравится
              http://www.cplusplus.com/reference/algorithm/lower_bound/ see::binary search code for lower bound. This site is very helpful. My doctor told me to see this five times a day. :)
            • 15 лет назад, скрыть # ^ |
               
              Проголосовать: нравится 0 Проголосовать: не нравится
              Thanks a lot for clearing lot of things but my doubt still persists. Let me rephrase the question.

              1. "how p=4 in lower_bound will give j=1?"
              for case 'a', vector v[0]=0 has only 1 element whose index or position is 0, which is represented by j. but then how j is giving value 1?

              All the vectors in this case are maintaining only single element then j must be 0 for all the cases. So why it is giving 1 in case of 'a'.

              2. if (j >= sz(v))   cnt++, p = v[0] + 1;

              this part of code is incrementing cnt or new headline and if p reaches end of the sorted values in vector then starting once again it from beginning. and

              else
                    p = v[j] + 1;

              this part is putting next value in sorted array of vector v in p.

              So where are we dividing the search space? I suppose we are only iterating in the vector.

              Likewise you mentioned in binary search we first search middle value then look at whether to search in [mid+1,high] or [low,mid+1], then further divide. but in this case how it is binary search.

              • 15 лет назад, скрыть # ^ |
                 
                Проголосовать: нравится 0 Проголосовать: не нравится
                1.j becomes 1 , because it reached the end of the list while searching for 4.
                (v.end() - v.begin() = 1)
                2.We are not doing binary search either in "if" or "else" part.
                rather the function lower_bound is doing binary search.[See c++ code of lower_bound]
                --------------------------------------
15 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

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

D was a bit tricky. Spent lot of time in debugging.