Codeforces Round #353 (Div. 2) Editorial
Difference between ru3 and ru4, changed 5,100 character(s)
Someday I will arrange C and D correctly :)↵

I will try to correct mistakes and expand editorial. Russian editorial will be published later.↵

[problem:675A]↵

Firstly, in case $c = 0$ we should output
Когда-нибудь я расположу C и D в правильном порядке :)↵

[problem:675A]↵

Во-первых, в случае $c = 0$ мы должны вывести
 YES ifесли $a = b$ else answer is, иначе вывести NO.↵

IfЕсли $b$ belongs to sequence $b = a + k * c$ where k is non-negative integer.↵

So answer is
принадлежит последовательности, то $b = a + k * c$, где $k$ является неотрицательным целым числом.↵

Поэтому ответ
 YES ifесли $(b - a) / c$ is non-negative integer else answer isявляется неотрицательным целым, иначе ответ NO.↵







<spoiler summary="Code">↵

~~~~~↵
#include <bits/stdc++.h>↵
 ↵
using namespace std;↵
 ↵
int main() {↵
    int a, b, c;↵
    cin >> a >> b >> c;↵
 ↵
    if (c == 0) {↵
        if (a == b) cout << "YESn";↵
        else cout << "NOn";↵
    } else {↵
        if ((b - a) % c == 0 && (b - a) / c >= 0) cout << "YESn";↵
        else cout << "NOn";↵
    }↵
}↵
~~~~~↵


</spoiler>↵







[problem:675B]↵

x a y↵

b m c↵

z d w↵

Number in the center may be any fromЧисло в центре может быть любым от 1 toдо $n$ because number in the center belongs to all subsquares $2\times 2$.↵
So, let's find answer with fixed number in the center and then multiply answer by $n$.↵

Let's iterate over all possible $x$.↵
Sums of each subsquare $2\times 2$ are the same so
, потому что оно лежит внутри всех квадратов $2\times 2$.↵
Поэтому мы можем найти ответ с фиксированным числом в центре и потом домножить его на $n$.↵

Переберем все возможные $x$.↵
Суммы в каждом квадрате $2\times 2$ одинаковы, поэтому
 $x + b + a + m = y + c + a + m$ andи $y = x + b - c$.↵

SimilarlyАналогично, $z = x + a - d$ andи $w = a + y - d = z + b - c$.↵

This square is legal if $1 \le y, z, w \le n$. We should just check it.↵

Also we can solve this problem in $O(1)$.↵



Квадрат с данными числам легален, если $1 \le y, z, w \le n$. Мы должны просто проверить это.↵

Это было решение за $O(n)$. Существует также решение за $O(1)$.




<spoiler summary="Code">↵

~~~~~↵
#include <iostream>↵

using namespace std;↵

int main() {↵
    int n, a, b, c, d;↵
    cin >> n >> a >> b >> c >> d;↵

    long long ans = 0;↵
    for (int x = 1; x <= n; x++) {↵
        int y = x + b - c;↵
        int z = x + a - d;↵
        int w = a + y - d;↵
        if (1 <= y && y <= n && 1 <= z && z <= n && 1 <= w && w <= n) {↵
            ans++;↵
        }↵
    }↵
    ans *= n;↵

    cout << ans << endl;↵
}↵

~~~~~↵


</spoiler>↵







[problem:675C]↵

We have array $a_i$ and should make all numbers in it be equal to zero with minimal number of operations.↵
Sum of all $a_i$ equals to zero.↵

We can divide array into parts of consecutive elements with zero sum.↵
If part has length $l$ we can use all pairs of neighbours in operations and make all numbers be equal to zero with $l - 1$ operations.↵

So, if we sum number of operations in each part we get $ans = n - k$ where $k$ is number of parts.↵
We should maximize $k$ to get the optimal answer.↵

One of the part consists of some prefix and probably some suffix. Each of other parts is subarray of $a$.↵

Let's calculate prefix sums. Each part has zero sum so prefix sums before each part-subarray are the same.↵

So we can calculate $f$ &mdash; number of occurencies of the most frequent number in prefix sums and answer will be equal to $n - f$.↵

Bonus: how to hack solutions with overflow?↵

У нас есть массив $a_i$ и мы должны обнулить все числа внутри него с помощью минимального количества операций.↵
Сумма всех чисел в массиве равна нулю.↵

Мы можем разделить массив на части с нулевой суммой, состоящие из последовательных элементов↵
(первый и последний элемент считаются последовательными).↵
Если часть имеет длину $l$, то мы можем обнулить ее с помощью $l - 1$ операции.↵

Следовательно, если мы сложим количество операций, то получим, что ответ равен $n - k$, где $k$ &mdash; количество частей.↵
Для того, чтобы ответ был минимальным, мы должны максимизировать $k$.↵

Одна из частей состоит из префикса и, возможно, суффикса массива. Остальные части являются подмассивами.↵

Давайте посчитаем префиксные суммы. Заметим, что префиксные суммы перед частями-подмассивами равны между собой,↵
так как сумма чисел в каждой части равна нулю.↵

Следовательно, ответ равен $n - f$, где $f$ &mdash; количество вхождений самого частого элемента среди префиксных сумм.↵

Бонус: как взламывать решения с переполнением?






<spoiler summary="Code">↵

~~~~~↵
#include <bits/stdc++.h>↵

using namespace std;↵

int main() {↵
    ios_base::sync_with_stdio(false); cin.tie(0);↵

    int n;↵
    cin >> n;↵
    map<long long, int> d;↵
    long long sum = 0;↵
    int ans = n - 1;↵
    for (int i = 0; i < n; i++) {↵
        int t;↵
        cin >> t;↵
        sum += t;↵
        d[sum]++;↵
        ans = min(ans, n - d[sum]);↵
    }↵

    cout << ans << endl;↵
}↵

~~~~~↵


</spoiler>↵









[problem:675D]↵

We have binary search tree (BST) and should insert number in it with good time complexity.↵

Let we should add number $x$. Find numbers $l < x < r$ which were added earlier, $l$ is maximal possible, $r$ is minimal possible↵
(all will be similar if only one of this numbers exists). We can find them for example with
У нас есть двоичное дерево поиска и мы должны уметь быстро добавлять в него числа.↵

Пусть сейчас мы должны добавить число $x$. Найдем ранее добавленные числа $l < x < r$ такие, что $l$ максимально возможное,↵
а $r$ минимально возможное. Если только одно из этих чисел существует, то рассуждения почти не меняются.↵
Мы можем найти $l$ и $r$, например, с помощью
 std::set andи upper_bound in C++.↵

We should keep sorted tree traversal (it's property of BST). So $x$ must be right child of vertex with $l$ or ↵
left child of vertex with $r$.↵

Let $l$ hasn't right child and $r$ hasn't left child. Hence lowest common ancestor (lca) of
, если вы пишете на C++.↵

Мы должны сохранять отсортированный обход дерева, так как это свойство двоичного дерева поиска.↵
Поэтому $x$ должно быть правым потомком вершины $l$ или левым потомком вершины $r$.↵

Пусть $l$ не имеет правого потомка и $r$ не имеет левого потомка. Тогда наименьший общий предок
 $l$ andи $r$ doesn't equal to(lca) не совпадает с $l$ orи $r$.↵
So lca is betweenНо тогда lca находится между $l$ andи $r$ in tree traversal. But it's impossible because $l$ is maximal possible and $r$ is minimal possible.↵
So $l$ has right child or $r$ has left child and we know exactly which of them will be parent of $x$.↵

That's all. Time complexity is
, а это невозможно, так как $l$ максимально, а $r$ минимально.↵
Получается противоречие, поэтому $l$ имеет правого потомка или $r$ имеет левого потомка.↵
Следовательно, мы точно знаем, кто из них станет предком $x$.↵

Это всё. Сложность решения
 $O(n \log n)$.↵







<spoiler summary="Code">↵

~~~~~↵
#include <iostream>↵
#include <set>↵
#include <map>↵

using namespace std;↵

int main() {↵
    ios_base::sync_with_stdio(false); cin.tie(0);↵

    set<int> numbers;↵
    map<int, int> left;↵
    map<int, int> right;↵

    int n, v;↵
    cin >> n >> v;↵
    numbers.insert(v);↵
    for (int i = 0; i < n - 1; i++) {↵
        cin >> v;↵
        auto it = numbers.upper_bound(v);↵
        int result;↵
        if (it != numbers.end() && left.count(*it) == 0) {↵
            left[*it] = v;↵
            result = *it;↵
        } else {↵
            it--;↵
            right[*it] = v;↵
            result = *it;↵
        }↵
        numbers.insert(v);↵
        cout << result;↵
        if (i == n - 2) cout << 'n';↵
        else cout << ' ';↵
    }↵
}↵

~~~~~↵


</spoiler>↵










[problem:675E]↵

Let the indexation will be from zero. So we should subtract one from all $a_i$.↵
Also let
Введем индексацию с нуля. Уменьшим каждый $a_i$ на единицу. Также сделаем $a_{n - 1} = $ равным $n - 1$.↵

Пусть $dp_i$ is sum of shortests pathes from&mdash; сумма кратчайших путей из $i$ toв $i + 1 \cdots n - 1$.↵

$dp_{n - 1} = 0$↵

$dp_i = dp_m - (a_i - m) + n - i - 1$
 where $m$ belongs to range from, где $m$ лежит между $i + 1$ toи $a_i$ andи $a_m$ is maximal.↵
We can find $m$ with segment tree or binary indexed tree or sparse table.↵

Now answer equals to sum of all $dp_i$.↵



максимально. Мы можем найти $m$ с помощью дерева отрезков / дерева Фенвика / разреженной таблицы.↵

Ответ равен сумме всех $dp_i$.




<spoiler summary="Code">↵

~~~~~↵
#include <bits/stdc++.h>↵

using namespace std;↵

const int maxn = 1 << 18;↵
pair<int, int> tree[maxn * 2];↵

void build(const vector<int> &a, int n) {↵
    for (int i = 0; i < n; i++) tree[maxn + i] = {a[i], i};↵
    for (int i = maxn - 1; i > 0; i--)↵
        tree[i] = max(tree[i * 2], tree[i * 2 + 1]);↵
}↵

int get(int l, int r) {↵
    pair<int, int> ans{-1, -1};↵
    for (l += maxn, r += maxn + 1; l < r; l >>= 1, r >>= 1) {↵
        if (l & 1) ans = max(ans, tree[l++]);↵
        if (r & 1) ans = max(ans, tree[--r]);↵
    }↵
    return ans.second;↵
}↵

int main() {↵
    ios_base::sync_with_stdio(false); cin.tie(0);↵

    int n;↵
    cin >> n;↵
    vector<int> a(n);↵
    a[n - 1] = n - 1;↵
    for (int i = 0; i < n - 1; i++) {↵
        cin >> a[i];↵
        a[i]--;↵
    }↵

    build(a, n);↵
    vector<long long> dp(n);↵
    long long ans = 0;↵
    dp[n - 1] = 0;↵
    for (int i = n - 2; i >= 0; i--) {↵
        int m = get(i + 1, a[i]);↵
        dp[i] = dp[m] - (a[i] - m) + n - i - 1;↵
        ans += dp[i];↵
    }↵

    cout << ans << 'n';↵
}↵

~~~~~↵


</spoiler>↵









History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en5 English komendart 2016-05-17 16:06:41 131
ru4 Russian komendart 2016-05-17 16:06:11 5100 Мелкая правка: 'ли $a = b$ иначе выв' -
ru3 Russian komendart 2016-05-16 22:18:48 48 Мелкая правка: ' + 1$ to $n - 1$ and $a_m' -> ' + 1$ to $a_i$ and $a_m'
en4 English komendart 2016-05-16 22:18:16 48 Tiny change: ' + 1$ to $n - 1$ and $a_m' -> ' + 1$ to $a_i$ and $a_m'
ru2 Russian komendart 2016-05-16 22:05:51 3329
en3 English komendart 2016-05-16 22:05:04 3289
en2 English komendart 2016-05-16 21:36:25 0 (published)
en1 English komendart 2016-05-16 21:35:55 3341 Initial revision for English translation
ru1 Russian komendart 2016-05-16 21:33:45 3341 Первая редакция (сохранено в черновиках)