# Разбор задач 2015 года Если Вы не знали как решать какую-то задачу и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас. :::warning Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя! ::: ## [1. Утренник](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2015_1) :::spoiler Разбор :::info Делаем то, о чем просят в условии. Не забудем про *long long*, так как $N * A_i$ не влезет в *int*. Асимптотика решения: $O(N)$. ::: :::spoiler Авторское решение (Pascal) ```pascal var a : array [1..1000000] of integer; s : int64; n, i: longint; k, q : int64; r : longint; begin read(n); s := 0; for i := 1 to n do begin read(a[i]); s := s + a[i] end; r := s mod n; if r = 0 then begin writeln('YES'); k := 0; q := s div n; for i := 1 to n do if a[i] > q then k := k + (a[i] - q); writeln(k) end else begin writeln('NO'); writeln(n - r) end; end. ``` ::: :::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun)) ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; int a[n]; for (int i = 0; i < n; ++i) cin >> a[i]; long long sum = 0; for (int i = 0; i < n; ++i) sum += a[i]; if (sum % n == 0) { cout << "YES" << endl; long long S = 0; for (int i = 0; i < n; ++i) S += abs(a[i] - sum / n); cout << S / 2 << endl; } else { cout << "NO" << endl; long long kol = sum / n; long long S = (kol + 1) * n; cout << S - sum << endl; } return 0; } ``` ::: ## [2. Тайные письма](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2015_2) :::spoiler Разбор :::info Давайте построим матрицу, которую нас просят, и выведем ее. Можно вывести формулу очередной буквы. Асимптотика: $O(N * M)$. ::: :::spoiler Авторское решение (Pascal) ```pascal var s : ansistring; m, n, i, j : longint; begin readln(n, m); readln(s); for i := 1 to n do for j := 1 to m do write(s[i + (j - 1) * n]); writeln; end. ``` ::: :::spoiler Код (C++, автор: [Wani4ka](https://codeforces.com/profile/Wani4ka)) ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n, m; string s; cin >> n >> m >> s; for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cout << s[j*n+i]; cout << endl; return 0; } ``` ::: ## [3. Новая архитектура](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2015_3) :::spoiler Разбор :::info Давате посчитаем $dp_{i,j}$ -- максимальный размер квадрата, у которого правый нижний угол находится в матрице на позиции $(i,j)$. Ответ будем считать как сумму всех $dp_{i,j}$, так как мы можем выбрать квадрат размера от $1$ до $dp_{i,j}$ (если текущая позиция не занята). Переход: 1. $dp_{i,j} = min(\{dp_{i-1,j-1}, dp_{i - 1,j}, dp_{i,j - 1}\}) + 1$, если клетка свободная. Асимптотика: $O(N^2)$. ::: :::spoiler Авторское решение (Pascal) ```pascal var n, m, i, j : longint; a : integer; k : int64; s : array [1..2000] of int64; p, v : int64; begin readln(n, m); k := 0; for j := 1 to m do begin read(a); s[j] := 1 - a; k := k + s[j] end; for i := 2 to n do begin read(a); p := s[1]; s[1] := 1 - a; k := k + s[1]; for j := 2 to m do begin read(a); if a = 1 then begin p := s[j]; s[j] := 0 end else begin v := p; p := s[j]; if s[j - 1] < v then v := s[j - 1]; if s[j] < v then v := s[j]; s[j] := v + 1; end; k := k + s[j] end; end; writeln(k); end. ``` ::: :::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun)) ```cpp #include <bits/stdc++.h> using namespace std; int n, m; vector<vector<int>> a; vector<vector<int>> dp; int main() { cin >> n >> m; a.resize(n, vector<int> (m)); dp.resize(n, vector<int> (m, 0)); for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> a[i][j]; for (int i = 0; i < n; ++i) if (a[i][0] == 0) dp[i][0] = 1; for (int i = 0; i < m; ++i) if (a[0][i] == 0) dp[0][i] = 1; for (int i = 1; i < n; ++i) for (int j = 1; j < m; ++j) if (a[i][j] == 0) dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1; long long ans = 0; for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) ans += dp[i][j]; cout << ans << endl; return 0; } ``` ::: ## [4. Путешественники](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2015_4) :::spoiler Разбор :::info Давайте бинарным поиском найдем ответ -- минимальное расстояние между двумя подряд посещенными городами. Перед этим отсортируем положения городов. В бинарном поиске жадным алгоритмом проверяем, можем ли мы выбрать города так, чтобы количество посещенных городов было как минимум $n$. Интуитивно понятно, что всегда выгодно начинать с самого ближнего города. Асмптотика решения: $O(log(max(A_i)) * M)$. ::: :::spoiler Авторское решение (Pascal) ```pascal var n, m, i, k: longint; x : longint; b: array[1..100000] of longint; idx : array[1..100000] of longint; lb, ub, st, st0: longint; procedure up(i, n: longint); var j: longint; x, mx, y: longint; begin x := b[i]; y:=idx[i]; repeat j := 2 * i; if j = n then mx := b[j] else if j < n then begin mx := b[j]; if b[j + 1] > mx then begin mx := b[j + 1]; j := j + 1 end end; if (j <= n) and (x < mx) then begin b[i] := mx; idx[i] := idx[j]; i := j end until i < j; b[i] := x; idx[i] := y; end; function min(x, y: longint): longint; begin if x < y then min := x else min := y end; begin read(n, m); for i := 1 to m do begin read(b[i]); idx[i] := i end; { pyramidal sort } for i := m div 2 downto 1 do up(i, m); for i := m downto 2 do begin x := b[1]; b[1] := b[i]; b[i] := x; x := idx[1]; idx[1] := idx[i]; idx[i] := x; up(1, i - 1) end; { binary search } lb := 0; ub := b[m] div n; st0 := 0; while lb < ub do begin st := (lb + ub) div 2; x := st; k := 0; for i := 1 to m do if b[i] >= x then begin k := k + 1; x := b[i] + st end; if k >= n then begin st0 := st; lb := st + 1 end else ub := st - 1 end; k := 0; x := st0; i := 1; while k < n do begin if b[i] >= x then begin if k <> 0 then write(' '); write(idx[i]); k := k + 1; x := b[i] + st0 end; i := i + 1 end; end. ``` ::: :::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun)) ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long n, m; cin >> n >> m; vector<pair<long long, long long>> a(m); for (int i = 0; i < m; ++i) { cin >> a[i].first; a[i].second = i; } sort(a.begin(), a.end()); long long l = 1, r = 1e18; long long ans = 0; while (l <= r) { long long mid = (l + r) >> 1; long long pos = mid; long long kol = 0; for (int i = 0; i < m; ++i) { if (a[i].first >= pos) { pos = a[i].first + mid; kol++; } } if (kol >= n) ans = mid, l = mid + 1; else r = mid - 1; } long long pos = ans; long long kol = 0; for (int i = 0; i < m; ++i) { if (a[i].first >= pos) { pos = a[i].first + ans; kol++; cout << a[i].second + 1 << " "; } if (kol == n) break; } return 0; } ``` :::