---
# System prepended metadata

title: Разбор задач 2015 года

---

# Разбор задач 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;
}
```
:::