[Logo] Форум DL
  [DL]  На главную страницу 
Индекс форума ->Олимпиадное программирование ->Методика подготовки к IOI 2007 - ... 1, 2
Автор Сообщение
Михаил Долинский (Online)

Темы: 1984
Сообщений: 47222

Мой профиль
Авторские описания решений (менять год)
Результаты (менять год)
Тестирование на Codeforces IOI 2002-2022
Тестирование на Яндекс.Контест IOI 2003-2018

С 2010 года существенно изменился формат IOI задач.

В этой теме предлагается описывать решения этих задач,
которые удалось сдать, хотя бы так, как это делает Павел Голуб для
задач финала ACM ICPC 2015
Только предлагаю для каждой задачи создавать своё сообщение, нажимая кнопку
"Ответить" в этой теме.
Я буду добавлять ссылки на добавленные описания решений в это сообщение.

Где можно найти разборы задач прошедших IOI на русском?

Состояние сдач на 23 июня 2015
- в скобках - количество полных решений на DL

2023 Editorial Задачи
Day 1
1. Closing Time
2. Longest Trip
3. Soccer
Day 2
1. Beech Tree
2. Overtaking
3. Robot Contest


2022 Editorial Задачи
Day 1
1. Catfish Farm
2. Prisoner Challenge
3. Radio Towers
Day 2
1. Digital Circuit
2. Rarest Insects
3. Thousands Islands

2021
Day 1 Обсуждение на CF
1. Candies Авторское
2. Keys Авторское
3. Parks Авторское
Day 2 Обсуждение на CF
1. DNA Авторское
2. Dungeons Авторское
3. Registers Авторское


2020
Day 1
1. Plants Авторское
2. Supertrees Авторское
3. Tickets Авторское
Day 2
1. Biscuits Авторское
2. Mushrooms Авторское
3. Stations Авторское

2019
Day 1
1. shoes Авторское
2. split Авторское
3. rect Авторское
Day 2
1. line Авторское
2. vision Авторское Лосев
3. walk Авторское

2018 2018-booklet
Day 1
1. combo Авторское
2. seats Авторское
3. werewolf Авторское
Day 2
1. doll Авторское
2. highway Авторское
3. meetings Авторское

2017 Все авторские
Day 1
1. nowruz Авторское
2. wiring Авторское
3. train Авторское
Day 2
1. prize Авторское
2. simurgh Авторское
3. books Авторское

2016 Все авторские Codeforces +1

Day_1 Гуленко
1. molecules Авторское Гуленко(Питон) Гуленко(Паскаль)
2. railroad Авторское Гуленко (Питон) Гуленко (Паскаль) +1
3. shortcut Авторское Гуленко: идея Питон Паскаль Костяной(полное решение)

Day_2
1. paint Авторское Костяной
2. messy Авторское
3. aliens Авторское


2015 Все авторские

Day_1
1. boxes (Авторское) Мосько
2. scales (Авторское)
3. teams (Авторское) Костяной

Day_2
1. horses Авторское Мосько
2. sorting Авторское Мосько
3. towns Авторское
Федор Коробейников

Темы: 46
Сообщений: 162

Мой профиль
IOI 2014 Все авторские

Day 1
1. Rail Авторское codeforces
2. Wall Авторское Коробейников
3. Game Авторское Коробейников

Day 2
1. Gondola Авторское
2. Friend Авторское
3. Holiday Авторское

IOI 2013

Day 1
1. Dreaming (2) - Мосько
2. Art Class (1)
3. Wombats (1)

Day 2
1. Cave (3)
2. Robots (0) - Коробейников
3. Game (0) - Коробейников , Codeforces


IOI 2012 Все авторские

Day 1 Авторские
1. Pebbling Odometer (1)
2. Parachute Rings (1)
3. Crayfish Scrivener (3) - Коробейников

Day 2 Авторские
1. Ideal City (0) - Chkhaidze
2. Last Supper (1)
3. Jousting Tournament (1)

IOI 2011

Day_1
1. GARDEN (0)
2. RACE (0) - Коробейников
3. RICEHUB (2) - Мосько

Day_2
1. CROCODILE (1)
2. ELEPHANTS (1)
3. PARROTS (0)
IOI 2010

Day 1
1. Cluedo (3)
2. Hotter Colder (0)
3. Quality of Living (0) - Chkhaidze
4. Language (0)

Day 2
1. Memory (1)
2. Traffic Congestion - Chkhaidze
3. Maze (0)
4. Saveit (0)



Сданы Задачи:
IOI 2013 Dreaming.
IOI 2013 Cave.
IOI 2013 Robots
IOI 2013 Wombats.
IOI 2013 Game.

IOI 2012 Crayfish Scrivener.
IOI 2012 Jousting Tournament
IOI 2012 Last Supper.

IOI 2011 Race.
IOI 2011 Ricehub.
IOI 2011 Crocodile.
IOI 2011 Elephants.
IOI 2011 Parrots.
В ближайшее время я постараюсь описать решения задач и оставлю ссылки на мой код.
______________________
Work hard and win a prize
Федор Коробейников

Темы: 46
Сообщений: 162

Мой профиль
IOI 2012 Crayfish Scrivener.
Заданная структура в условии - это стек с возможностью отката. Делаем стек персистентным и мы решили задачу. Сделать стек персистентным очень просто. Давайте занумируем все элементы, которые были когда-либо в стеке. И от каждого элемента проведём ребро в предыдущий элемент стека. Данная структура образует дерево. Состояние стека задаёт номер вершины.
Доставать какой-то элемент стека можно с помощью двоичных подъёмов. Про двоичные подъёмы можно почитать здесь: http://e-maxx.ru/algo/lca_simpler .
Код http://pastie.org/private/7bait4wijlotnyrir4g .
______________________
Work hard and win a prize
Федор Коробейников

Темы: 46
Сообщений: 162

Мой профиль
IOI 2013 - Robots.
Решение довольно простое. Давайте слабых роботов отсортируем по их максимальному весу, а маленьких по максимальному размеру. Для каждого слабого робота определим сколько он сможет убрать игрушек. Понятно, что можно перебрать бинарным поиском ответ. Как проверить можно ли всё убрать за x секунд. Давайте будем выбирать игрушки, которых уберут слабые роботы, а остальные попробуем жадно убрать маленькими. Давайте набирать игрушки в очередь и смотреть сколько слабых роботов их могут убрать. Если настал момент что k*x>=больше числа игрушек, где k это сколько роботов убирают данный набор, то можно удалить эти игрушки из очереди и рассмотрения, так как наши роботы их уберут. В конце у нас осталась очередь игрушек, которые мы не убрали. Теперь нам нужно убрать часть из них, что бы остальные слабые роботы успели убрать. Давайте скажем, что queue_size-k*x игрушек с минимальным размером будут убирать маленькие роботы. Так же игрушки вес которых больше максимального лимита веса слабых роботов. Проверить Остальные проверить жадностью.
Код http://pastie.org/10255366 (написан не в формате IOI).
______________________
Work hard and win a prize
Федор Коробейников

Темы: 46
Сообщений: 162

Мой профиль
IOI 2013 Game.
Заметим, что запросов update довольно мало. Давайте будем запросы update накапливать в каком-то маленьком множестве. Как только размер множества станет больше 800 мы все элементы маленького множества перенесём в большое. Как отвечать на запрос узнать gcd на подматрице. Можно сначала проверить элементы маленького множества за линию. Но с большим уже тяжелее. Давайте упорядочим координаты большого множества по возрастанию x, а затем y(Грубо говоря когда мы добавили маленькое множество в большое мы отсортируем наше большое заново). Теперь давайте разобьём наше большое множество на блоки по 100 и внутри блока отсортируем всё по y и для этого порядка внутри блока посчитаем простую динамику F[i][j] - это gcd на отрезке i до i+2^j-1. Теперь мы сможем отвечать на запрос в большом множестве. Давайте найдём отрезок большого множества такой что содержит все координаты, которые подходят под x координаты запроса. Теперь какие-то блоки полностью попали в запрос в них посчитать gcd можно используя то что мы отсортировали по y всё заранее внутри блока и нам просто нужно будет взять gcd на отрезке(это можно сделать с помощью динамики f[i][j]. Для отрезка l r - gcd(f[l][k],f[r-2^k+1][k]). k - это старший бит r-l+1). А те что не попали полностью в блок проверим за размер блока. Асимптотика O(M*sqrt(N)*log(MAX_VALUE)).
Код - http://pastie.org/10256087 .
______________________
Work hard and win a prize
Федор Коробейников

Темы: 46
Сообщений: 162

Мой профиль
IOI 2011 Race.
Стандартный алгоритм центроидная декомпозиция дерева или разделяй и властвуй по дереву. Про этот приём можно почитать здесь http://pastie.org/private/xpboy5nbryb0g5rqulo9nq
код - http://pastie.org/10256137 .
______________________
Work hard and win a prize
Владислав Мосько

Темы: 20
Сообщений: 68

Мой профиль
IOI 2011 Rice hub.

Условие:
Дан отрезок [1;L], на котором расположены R пунктов выработки риса, их координаты - 1<=X[1]<=X[2]<=...<=X[R].
Есть бюджет В. Мы можем собрать рис с точки X в пункт сбора в точке T за |T-X| денег.
Нужно расположить пункт сбора на отрезке [1;L] и собрать рис из как можно большего количества точек.

Решение:
Одно из самых важных наблюдений, которое очень известно и очевидно, - по крайней мере один из оптимальных пунктов
сбора может быть найден среди значений X[] (это используется во многих задачах такого типа).
Хорошо, теперь у нас есть R кандидатов на ответ и нужно каждый проверить за какую-то небольшую сложность.

Давайте научимся это делать для какой-то позиции i. (Проверяем значение X[i]).
Пусть мы зафиксировали какое-то число H и говорим, что с пунктов [i-H+1;i] мы точно соберем рис.
Во-первых, нужно убедиться, что это не займет больше B денег.
Если все хорошо, можем дихотомией найти такое максимальное Q, что [i+1;i+Q] мы тоже сможем взять.
Осталось понять, как мы будем выбирать H.
Понятно, что если рассмотреть функцию func(H), которая при фиксированной позиции i и данном H говорит,
с какого количества пунктов выработки мы сможем собрать рис, то она будет иметь такой вид:
Пусть U[1]<U[2]<U[3]...<U[k], тогда найдется L такое, что func(U[1])<=func(U[2])<=...<=func(U[L]); func(U[L])>=func(U[L+1])>=func(U[L+2])...>=func(U[k]).
Видно, что точку U[L] можно найти трихотомией.

Код: http://ideone.com/cKYo9H

Владислав Мосько

Темы: 20
Сообщений: 68

Мой профиль
IOI 2013 Dreaming.

Условие:
Дан взвешенный неориентированный граф, компоненты связности которого являются деревьями (лес).
В графе N вершин и M ребер.
Нужно сделать его связным, построив N-M-1 ребро стоимости L и минимизировать итоговый диаметр графа.

Решение:
Для начала рассмотрим каждую компоненту-дерево в отдельности, найдем ее диаметр, радиус и центр.
Далее отсортируем все компоненты по невозрастанию диаметра и будем в таком порядке объединять (можно доказать, что это оптимально). При этом нужно уметь пересчитывать новый диаметр, центр и радиус.
Это делается так.
Пусть данные первой компоненты - diam1, center1, rad1;
Данные второй компоненты - diam2, center2, rad2.
Тогда если обозначить за diamM, centerM, radM данные компоненты, образующейся в результате слияния этих двух, утверждается следующее:
diamM = rad1 + rad2 + L
centerM - либо center1 либо center2 в зависимости от получающихся радиусов соответственно.
Если мы выберем center1 в качестве centerM, тогда radM = max(rad1, rad2 + L), а если выберем center2, radM = max(rad1 + L, rad2).
Поскольку radM, очевидно, нужно минимизировать, выберем лучший вариант.
Однако, возможен случай, когда diam1 или diam2 больше, чем rad1 + rad2 + L, такой случай стоит рассмотреть отдельно.

Вспомогательные методы:
1. Нахождения диаметра дерева
1.1 Выберем произвольную вершину root
1.2 Найдем самую далекую от root вершину с помощью DFS и обозначим ее v1
1.3 Найдем самую далекую от v1 вершину и обозначим ее v2
Утверждается, что путь v1->v2 является диаметром дерева
2. Нахождение центра дерева
2.1 Утверждается, что центр дерева принадлежит его диаметру
2.2 (Возможно, можно сделать это проще, я писал первое, что пришло в голову)
Воспользуемся трихотомией и на пути v1->v2 найдем такую вершину v, что величина max(dist(v,v1),dist(v,v2)) минимальна. Тогда, очевидно, v и будет являться центром.
Остается вопрос, как выполнить операцию такого вида:
go(v,dest,path) - узнать, какая вершина лежит на расстоянии path от v если двигаться по направлению к dest.
Это делается аккуратными двоичными подъемами и рассмотрением случаев.
Теория:
http://e-maxx.ru/algo/dfs
http://e-maxx.ru/algo/connected_components
http://e-maxx.ru/algo/lca_simpler
Код: http://ideone.com/hfqY9m
Nugzar Chkhaidze

Темы: 0
Сообщений: 3

Мой профиль
IOI 2010 Traffic Congestion
Count sums of subtrees of every city.
Let SUM be sum of all populations.
Traverse graph using DFS.
Let sum of subtree V including population of V be subtree[V]. If the arena city is at X-th city then traffic coming from its child Y will be subtree[Y].
Traffic coming from X’s parent vertex will be (SUM-subtree[x]) .
Find maximum among subtrees’ values of X and (SUM-subtree[x]). This maximum of them will be the biggest traffic, if the arena city is in X.
Calculate the biggest traffics for all placements of the arena city and print out the index with minimum value among those.
Time complexity O(n)
http://pastebin.com/GZUs7yxb
Nugzar Chkhaidze

Темы: 0
Сообщений: 3

Мой профиль
IOI 2010 Quality of Living
Find answer of the problem using binary search.
Check if answer x.
Transform array: if a[i][j]>x replace with 1, if a[i][j]=x then 0, if a[i][j]<0 then 1;
Using dynamic programming calculate array d.
d[i][j]=(sum of rectangle with vertices (1,1) and (I,j)).
Using array-d we can calculate sum of every rectangle in O(1). (see in code)
With a sum of a rectangle we can understand whether median in the rectangle is bigger, smaller than x or equal to x.
Check sum of every rectangle with sizes H and W.
If one of them is negative then the answer of the problem is less than X.
If sums of all of rectangles are positive then answer is bigger than X.
If one (or more) of rectangle’s sum is zero and others are positive then the answer is X.
Time complexity O(n*m*lg(n*m))
http://pastebin.com/asLTgnYH

Nugzar Chkhaidze

Темы: 0
Сообщений: 3

Мой профиль
IOI 2012 Ideal City
We can move only vertically or horizontally, so we can solve this problem firstly only on horizontal lengths, then only on vertical lengths.
Firstly, solve on horizontals.
Unite vertically neighbor vertices in groups using DSU, because they are considered the same vertices because we count only horizontal moves. While uniting we can also count the sizes of groups.
Check for every vertex if it has a horizontal neighbor, if yes then make an edge between the groups of these two vertices(Using set we can control not to make multiple edges between the same groups). Because there is not a “hole” in a map of the city, then the graph of groups will have no cycles, therefore it will be a tree.
If group i has v[i] vertices in it, group j - v[j] vertices, and length between the groups is d, then the sum of horizontal distances between vertices of the groups will be d*v[i]*v[j].
We can check every I and J and sum up every (d*v[i]*v[j]) but it will need n^2 time, which is too slow. Linear time approach is to count sum-s of subtree for each vertex (group). And then sum up (subtree[x])*(n-subtree[x]), which will result in the same answer as the sums of (d*v[i]*v[j]).
After counting answer for horizontals, we can swap x and y-s of vertices and make same operations for the second time (for swapped values) to find answer for verticals.
Time complexity O(n*lg(n))
http://e-maxx.ru/algo/dsu
http://pastebin.com/sm5hFJ4a
Михаил Долинский (Online)

Темы: 1984
Сообщений: 47222

Мой профиль
From: Алексей Гуленко
Sent: Tuesday, April 11, 2017 2:11 AM

molecules: дихотомия по ширине скользящего окна на сортированном массиве (с промежуточными ДП возиться не стал).
railroads: перебор > ДП > граф (существование Эйлерова цикла с допущениями) > граф (#3 + минимальное основное дерево по компонентам)
shortcut: дихотомия по ответу с возрастающе сложными оптимизациями проверки (даже не брался)
Прилагаю решения на Python как наименее сложные. 
Михаил Долинский (Online)

Темы: 1984
Сообщений: 47222

Мой профиль


Гуленко Алексей:

molecules: дихотомия по ширине скользящего окна на сортированном массиве (с промежуточными ДП возиться не стал). 


Питон:

__all__ = ['find_subset']

SMALLER, BIGGER = object(), object()

def test (k, smin, smax, w):
    s = sum( w[:k] )
    if smin <= s <= smax:
        return 0
    smaller, bigger = s < smin, s > smax
    for i in range(k, len(w)):
        s = s - w[i-k] + w[i]
        smaller = smaller or s < smin
        bigger = bigger or s > smax
        if smin <= s <= smax:
            return i-k+1
    assert smaller != bigger
    return (SMALLER if smaller else BIGGER)

def find (smin, smax, w, idx):
    w = sorted(w)
    l, r = 0, len(w)+1
    while l + 1 < r:
        m = (l+r+1) // 2
        if test(m, smin, smax, w) is BIGGER:
            r = m
        else:
            l = m
    m = test(l, smin, smax, w)
    return ([] if m in {SMALLER, BIGGER} else idx[m:m+l])

def find_subset (l, u, w):
    idx = sorted(range( len(w) ), key=lambda i: w[i])
    return find(l, u, w, idx)

Михаил Долинский (Online)

Темы: 1984
Сообщений: 47222

Мой профиль


Гуленко Алексей:

molecules: дихотомия по ширине скользящего окна на сортированном массиве (с промежуточными ДП возиться не стал). 
Паскаль
Unit Molecules;
{$Mode ObjFPC}
Interface
  TYPE
    TInts = Array of LongInt;

  Function Find_Subset (L, U : LongInt;  W : TInts): TInts;

Implementation

  Function Test (K, SMin, SMax : LongWord;  Const W, Idx : TInts): LongWord;
  Var
    S                   : QWord = 0;
    i, N                : LongWord;
    Smaller, Bigger     : Boolean;
  Begin
    For i:=1 To K
      Do Inc(S, W[ Idx[i-1] ]);
    If (SMin <= S) and (S <= SMax)
      Then Exit(1);
    Smaller := S < SMin;
    Bigger := S > SMax;
    N := Length(W);
    For i:=K+1 To N Do Begin
      S := S - W[ Idx[i-K-1] ] + W[ Idx[i-1] ];
      Smaller := Smaller or (S < SMin);
      Bigger := Bigger or (S > SMax);
      If (SMin <= S) and (S <= SMax)
        Then Exit(i-K+1);
    End;
    If Smaller = Bigger
      Then Halt(1);
    If Smaller
      Then Exit(0)
      Else Exit(N + 1);
  End;

  Function Find (SMin, SMax : LongWord;  Const W, Idx : TInts): TInts;
  Var
    N, L, R, M  : LongWord;
  Begin
    N := Length(W);
    L := 0;   R := N + 1;
    While L + 1 < R Do Begin
      M := (L+R+1) div 2;
      If Test(M, SMin, SMax, W, Idx) > N
        Then R := M
        Else L := M;
    End;
    M := Test(L, SMin, SMax, W, Idx);
    If (0 < M) and (M <= N)
      Then Exit( Copy(Idx, M-1, L) );
    SetLength(Result, 0);
  End;

  Procedure Sort (Var Idx : TInts;  Const W : TInts);
  Var
    Buff        : TInts;
  
    Procedure _Add (Var i, k : LongWord);   Inline;
    Begin
      Idx[k] := Buff[i];
      Inc(i);   Inc(k);
    End;
  
    Procedure _Sort (L, R : LongWord);
    Var
      i, j, k, C        : LongWord;
    Begin
      If L = R
        Then Exit;
      C := (L+R) div 2;
      _Sort(L, C);
      _Sort(C+1, R);
      For k:=L To R
        Do Buff[k] := Idx[k];
      k := L;   i := L;   j := C+1;
      While (i <= C) and (j <= R)
        Do If W[ Buff[i] ] <= W[ Buff[j] ]
          Then _Add(i, k)
          Else _Add(j, k);
      While (i <= C) Do _Add(i, k);
      While (j <= R) Do _Add(j, k);
    End;
  
  Begin
    SetLength(Buff, Length(W));
    _Sort(0, Length(W)-1);
  End;

  Function Find_Subset (L, U : LongInt;  W : TInts): TInts;
  Var
    Idx : TInts;
    i   : LongWord;
  Begin
    SetLength(Idx, Length(W));
    For i:=1 To Length(W)
      Do Idx[i-1] := i-1;
    Sort(Idx, W);
    Exit( Find(L, U, W, Idx) );
  End;

END.

Михаил Долинский (Online)

Темы: 1984
Сообщений: 47222

Мой профиль


Гуленко Алексей:

railroads: перебор > ДП > граф (существование Эйлерова цикла с допущениями) > граф (#3 + минимальное основное дерево по компонентам) 


Питон:

1.
__all__ = ['plan_roller_coaster']

def find_min (l, speed, s, t, not_used):
    result, found = None, False
    for i in list(not_used):
        not_used.remove(i)
        d = max(0, speed-s[i])
        x = find_min(l+d, t[i], s, t, not_used)
        result = (result if found and x > result else x)
        found = True
        not_used.add(i)
    return (result if found else l)

def plan_roller_coaster (s, t):
    return find_min(0, 0, s, t, set(range( len(s) )))


2.
__all__ = ['plan_roller_coaster']

def bits (mask):
    i, j = 1, 0
    while mask > 0:
        if mask & i > 0:
            mask -= i
            yield j
        i, j = i+i, j+1

def plan_roller_coaster (s, t):
    n = len(s)
    d = [[None]*n for i in range(1 << n)]
    for i in range(n):
        d[1 << i][i] = 0
    for mask in range(1 << n):
        b = set( bits(mask) )
        for i in b:
            if d[mask][i] is not None:
                for j in set(range(n)) - b:
                    d1 = d[mask][i] + max(0, t[i]-s[j])
                    m = mask | (1 << j)
                    d[m][j] = (d1 if d[m][j] is None or d1 < d[m][j] else d[m][j])
    return min( d[(1 << n) - 1] )


3.
from bisect import bisect_left as find

__all__ = ['plan_roller_coaster']

MINX, MAXX = 1, 10**9
YES, NO = 0, 1


class DSF (object):
    __len__ = lambda o: o.size
    
    def __init__ (self, n):
        self.size, self._r, self._d = n, [0]*n, list( range(n) )
    
    def __getitem__ (self, u):
        if self._d[u] != u:
            self._d[u] = self[ self._d[u] ]
        return self._d[u]
    
    def merge (self, u, v):
        u, v = self[u], self[v]
        if u == v:
            return False
        if self._r[u] == self._r[v]:
            self._r[u] += 1
        if self._r[u] < self._r[v]:
            self._d[u] = v
        else:
            self._d[v] = u
        self.size -= 1
        return True


def plan_roller_coaster (s, t):
    s, t = s+[MAXX], t+[MINX]
    points = sorted( set(s+t) )
    dsf, d = DSF( len(points) ), [0]*len(points)
    for u, v in zip(s, t):
        u, v = find(points, u), find(points, v)
        dsf.merge(u, v)
        d[u] += 1
        d[v] -= 1
    opened = 0
    for i, x in enumerate(d):
        opened += x
        if opened > 0:
            return NO
        elif opened < 0:
            dsf.merge(i, i+1)
    assert opened == 0
    return (YES if len(dsf) == 1 else NO)


FULL.
from bisect import bisect_left as find

__all__ = ['plan_roller_coaster']

MINX, MAXX = 1, 10**9


class DSF (object):
    __len__ = lambda o: o.size
    
    def __init__ (self, n):
        self.size, self._r, self._d = n, [0]*n, list( range(n) )
    
    def __getitem__ (self, u):
        if self._d[u] != u:
            self._d[u] = self[ self._d[u] ]
        return self._d[u]
    
    def merge (self, u, v):
        u, v = self[u], self[v]
        if u == v:
            return False
        if self._r[u] == self._r[v]:
            self._r[u] += 1
        if self._r[u] < self._r[v]:
            self._d[u] = v
        else:
            self._d[v] = u
        self.size -= 1
        return True


def plan_roller_coaster (s, t):
    s, t = s+[MAXX], t+[MINX]
    points = sorted( set(s+t) )
    n = len(points)
    dx = [x1-x for x, x1 in zip(points, points[1:])]
    dsf, d = DSF(n), [0]*n
    for u, v in zip(s, t):
        u, v = find(points, u), find(points, v)
        dsf.merge(u, v)
        d[u] += 1
        d[v] -= 1
    q = d.pop()
    result, opened, edges = 0, 0, []
    for i, x in enumerate(d):
        opened += x
        if opened == 0:
            edges.append(i)
        else:
            dsf.merge(i, i+1)
            result += max(0, opened * dx[i])
    assert opened == -q
    edges.sort(key=dx.__getitem__)
    for u in edges:
        v, x = u+1, dx[u]
        if dsf[u] != dsf[v]:
            result += x
            dsf.merge(u, v)
    return result

 
Индекс форума ->Олимпиадное программирование ->Методика подготовки к IOI 2007 - ... 1, 2
Time:0,059