# Разбор задач 2019 года
Если Вы не знали как решать какую-то задачу и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас.
:::warning
Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя!
:::
## [1. Достижение амплитуды](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2019_1)
:::spoiler Разбор
:::info
Заметим, что ответ равен $2 * n - 1$.
Асимптотика: $O(1)$.
:::
:::spoiler Код (C++, автор: [SashOK_Yatsuk](https://codeforces.com/profile/SashOK_Yatsuk))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
cout << 2 * n - 1 << endl;
return 0;
}
```
:::
## [2. Ограниченное колебание](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2019_2)
:::spoiler Разбор
:::info
Давайте заметим, что у нас есть 4 случая:
1. Шарик еще не ударился и он находится в положительной координате.
2. Шарик еще не ударился и он находится в отрицательной координате.
3. Шарик уже ударился и он находится в отрицательной координате.
4. Шарик уже ударился и он находится в положительной координате.
Давайте разберем их.
:::
:::spoiler Код (C++, автор: [Wani4ka](https://codeforces.com/profile/Wani4ka))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
long long n, R;
cin >> n >> R;
n %= R * 8;
if (n <= R * 2) {
if (n % 2 == 0)
cout << "-" << n / 2 << endl;
else cout << (n + 1) / 2 << endl;
} else if (n <= R * 4) {
if (n % 2 == 0)
cout << "-" << (R * 4 - n) / 2 << endl;
else cout << (R * 4 - n) / 2 << endl;
} else if (n <= R * 6) {
if (n % 2 == 0)
cout << (n - R * 4) / 2 << endl;
else cout << "-" << (n - R * 4 + 1) / 2 << endl;
} else {
if (n % 2 == 0)
cout << (R * 8 - n) / 2 << endl;
else cout << "-" << (R * 8 - n) / 2 << endl;
}
return 0;
}
```
:::
## [3. Трехканальное оповещение](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2019_3)
:::spoiler Разбор
:::info
Это одна из самых сложных задач из Витебских районов. С другой стороны, не такая уж и сложная.
Давайте забинарим минимально число звонков.
Теперь, меняя приоритеты звонков, проверяем, может ли каждый из звонящих совершить >= mid звонков.
Немного уточнений:
1. Если человеку может позвонить только один помощник, то он ему точно позвонит, т.е в приоритеты пихать таких людей не нужно.
2. Если человеку может позвонить все 3 помощника, то нам не нужны приоритеты для таких звонков.
3. Приоритеты могут быть на "одиночные" звонки и "двойные" звонки.
4. В начале мы пихаем(порядок обработки) все звонки по двойному приоритету, а распределяем по одиночному приоритету. Для лучшего понимания, смотрите код.
Асимптотика: $O(6 * 6 * (m1 + m2 + m3) * log(N / 3))$.
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> st(3);
vector<vector<bool>> use(3);
int n;
vector<int> m(3);
vector<int> ans;
int kol_all = 0;
vector<int> all;
vector<int> line(3);
int kol_1_2 = 0;
int kol_1_3 = 0;
int kol_2_3 = 0;
vector<int> can_1_2;
vector<int> can_1_3;
vector<int> can_2_3;
bool prioritet(int x, int y, vector<int> &pr) {
int pos_1 = -1, pos_2 = -1;
for (int i = 0; i < 3; ++i)
if (pr[i] == x) pos_1 = i;
else if (pr[i] == y) pos_2 = i;
return pos_1 < pos_2;
}
void viber_fst(pair<int, int> tech, vector<int> &lol_1_2, vector<int> &lol_1_3, vector<int> &lol_2_3) {
if (tech == make_pair(0, 1))
ans[lol_1_2.back()] = 1, lol_1_2.pop_back();
else if (tech == make_pair(0, 2))
ans[lol_1_3.back()] = 1, lol_1_3.pop_back();
else ans[lol_2_3.back()] = 2, lol_2_3.pop_back();
}
void viber_scd(pir<int, int> tech, vector<int> &lol_1_2, vector<int> &lol_1_3, vector<int> &lol_2_3) {
if (tech == make_pair(0, 1))
ans[lol_1_2.back()] = 2, lol_1_2.pop_back();
else if (tech == make_pair(0, 2))
ans[lol_1_3.back()] = 3, lol_1_3.pop_back();
else ans[lol_2_3.back()] = 3, lol_2_3.pop_back();
}
bool ok(int mid) {
if (min({m[0], m[1], m[2]}) < mid) return 0;
vector<int> prior(3);
for (int i = 0; i < 3; ++i) prior[i] = i;
do {
vector<pair<int, int>> lol;
lol.push_back({0, 1});
lol.push_back({0, 2});
lol.push_back({1, 2});
do {
vector<pair<int, int>> kek;
for (int i = 0; i < 3; ++i)
if (lol[i] == make_pair(0, 1))
for (int j = 0; j < kol_1_2; ++j)
kek.push_back({0, 1});
else if (lol[i] == make_pair(0, 2))
for (int j = 0; j < kol_1_3; ++j)
kek.push_back({0, 2});
else if (lol[i] == make_pair(1, 2))
for (int j = 0; j < kol_2_3; ++j)
kek.push_back({1, 2});
vector<int> kk(3);
kk[0] = line[0];
kk[1] = line[1];
kk[2] = line[2];
for (int i = 0; i < kek.size(); ++i)
if (prioritet(kek[i].first, kek[i].second, prior) && kk[kek[i].first] < mid)
kk[kek[i].first]++;
else kk[kek[i].second]++;
int kol = 0;
for (int i = 0; i < 3; ++i)
kol += max(0, mid - kk[i]);
if (kol <= kol_all) return 1;
} while (next_permutation(lol.begin(), lol.end()));
} while (next_permutation(prior.begin(), prior.end()));
return 0;
}
void go(int mid) {
vector<int> prior(3);
for (int i = 0; i < 3; ++i)
prior[i] = i;
do {
vector<pair<int, int>> lol;
lol.push_back({0, 1});
lol.push_back({0, 2});
lol.push_back({1, 2});
do {
vector<pair<int, int>> kek;
for (int i = 0; i < 3; ++i)
if (lol[i] == make_pair(0, 1))
for (int j = 0; j < kol_1_2; ++j)
kek.push_back({0, 1});
else if (lol[i] == make_pair(0, 2))
for (int j = 0; j < kol_1_3; ++j)
kek.push_back({0, 2});
else if (lol[i] == make_pair(1, 2))
for (int j = 0; j < kol_2_3; ++j)
kek.push_back({1, 2});
vector<int> kk(3);
kk[0] = line[0];
kk[1] = line[1];
kk[2] = line[2];
for (int i = 0; i < kek.size(); ++i)
if (prioritet(kek[i].first, kek[i].second, prior) && kk[kek[i].first] < mid)
kk[kek[i].first]++;
else kk[kek[i].second]++;
int kol = 0;
for (int i = 0; i < 3; ++i)
kol += max(0, mid - kk[i]);
if (kol <= kol_all) {
kk[0] = line[0];
kk[1] = line[1];
kk[2] = line[2];
vector<int> nonka_1_2 = can_1_2;
vector<int> nonka_1_3 = can_1_3;
vector<int> nonka_2_3 = can_2_3;
for (int i = 0; i < kek.size(); ++i)
if (prioritet(kek[i].first, kek[i].second, prior) && kk[kek[i].first] < mid)
kk[kek[i].first]++, viber_fst(kek[i], nonka_1_2, nonka_1_3, nonka_2_3);
else kk[kek[i].second]++, viber_scd(kek[i], nonka_1_2, nonka_1_3, nonka_2_3);
int tech = kol_all;
vector<int> now = all;
for (int i = 0; i < 3; ++i)
while(kk[i] < mid)
tech--, kk[i]++, ans[now.back()] = i + 1, now.pop_back();
for (int i = 0; i < tech; ++i)
ans[now.back()] = 1, now.pop_back();
return;
}
} while (next_permutation(lol.begin(), lol.end()));
} while (next_permutation(prior.begin(), prior.end()));
}
int main() {
scanf("%i%i%i%i", &n, &m[0], &m[1], &m[2]);
for (int i = 0; i < 3; ++i) {
use[i].resize(n + 1, 0);
for (int j = 0; j < m[i]; ++j) {
int x;
scanf("%i", &x);
if (use[i][x]) continue;
use[i][x] = 1;
st[i].push_back(x);
}
m[i] = st[i].size();
}
ans.resize(n + 1, 0);
for (int i = 1; i <= n; ++i) {
int kol = 0;
for (int j = 0; j < 3; ++j)
if (use[j][i]) kol++;
if (kol == 3) {
kol_all++;
all.push_back(i);
} else if (kol == 1) {
for (int j = 0; j < 3; ++j)
if (use[j][i]) {
ans[i] = j + 1;
line[j]++;
break;
}
} else {
if (use[0][i] && use[1][i])
kol_1_2++, can_1_2.push_back(i);
else if (use[0][i] && use[2][i])
kol_1_3++, can_1_3.push_back(i);
else kol_2_3++, can_2_3.push_back(i);
}
}
int l = min({line[0], line[1], line[2]}), r = min(n / 3, min({m[0], m[1], m[2]}));
int ot = -1;
while (l <= r) {
int mid = (l + r) >> 1;
if (ok(mid))
l = mid + 1, ot = mid;
else r = mid - 1;
}
go(ot);
for (int i = 1; i <= n; ++i)
printf("%i%c", ans[i], ' ');
return 0;
}
```
:::
:::spoiler Код (C++, автор: [mrboorger](https://codeforces.com/profile/mrboorger))
```cpp
#pragma gcc target("sse,sse2,sse3,ssse3,sse4")
#pragma gcc optimize("-Ofast")
//
#include <bits/stdc++.h>
#define F first
#define S second
#define ll long long
#define pb push_back
using namespace std;
const int maxn = 1e6 + 23;
const int inf = 1e9;
bool a[3][maxn];
int m[3];
int sum[3];
int answ[maxn];
int kek[maxn];
int kek01[maxn];
int kek02[maxn];
int kek12[maxn];
int cnt = 0;
int cnt01 = 0;
int cnt02 = 0;
int cnt12 = 0;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n >> m[0] >> m[1] >> m[2];
for(int k = 0; k < 3; ++k)
for(int i = 0; i < m[k]; ++i)
{
int x;
cin >> x;
--x;
a[k][x] = true;
}
for(int i = 0; i < n; ++i)
{
if (a[0][i] && a[1][i] && a[2][i])
{
kek[cnt++] = i;
a[0][i] = false;
a[1][i] = false;
a[2][i] = false;
}
if (a[0][i] && !a[1][i] && !a[2][i])
{
answ[i] = 0;
++sum[0];
a[0][i] = false;
}
if (!a[0][i] && a[1][i] && !a[2][i])
{
answ[i] = 1;
++sum[1];
a[1][i] = false;
}
if (!a[0][i] && !a[1][i] && a[2][i])
{
answ[i] = 2;
++sum[2];
a[2][i] = false;
}
//
if (a[0][i] && a[1][i])
{
kek01[cnt01++] = i;
a[0][i] = false;
a[1][i] = false;
}
if (a[0][i] && a[2][i])
{
kek02[cnt02++] = i;
a[0][i] = false;
a[2][i] = false;
}
if (a[1][i] && a[2][i])
{
kek12[cnt12++] = i;
a[1][i] = false;
a[2][i] = false;
}
}
int l = 0, r = (n + 2) / 3;
int ans = -1;
int lola = 0;
int lolb = 0;
int lolc = 0;
while(l <= r)
{
int mid = (l + r) / 2;
bool f = false;
int biba = 0;
int bibb = 0;
int bibc = 0;
for(int a = 0; a <= cnt01; ++a)
{
int b = max(mid - sum[0] - a, 0);
int c = max(mid - sum[1] - cnt01 + a, 0);
if (b > cnt02 || c > cnt12) continue;
if (sum[0] + a + b >= mid && sum[1] + cnt01 - a + c >= mid && sum[2] + cnt02 - b + cnt12 - c >= mid)
{
f = true;
biba = a;
bibb = b;
bibc = c;
}
}
if (f)
{
if (mid > ans)
{
ans = mid;
lola = biba;
lolb = bibb;
lolc = bibc;
}
l = mid + 1;
}
else
r = mid - 1;
}
sum[0] += lola + lolb;
sum[1] += cnt01 - lola + lolc;
sum[2] += cnt02 - lolb + cnt12 - lolc;
for(int i = 0; i < lola; ++i)
answ[kek01[i]] = 0;
for(int i = lola; i < cnt01; ++i)
answ[kek01[i]] = 1;
for(int i = 0; i < lolb; ++i)
answ[kek02[i]] = 0;
for(int i = lolb; i < cnt02; ++i)
answ[kek02[i]] = 2;
for(int i = 0; i < lolc; ++i)
{
answ[kek12[i]] = 1;
}
for(int i = lolc; i < cnt12; ++i)
answ[kek12[i]] = 2;
int d[3] = {0, 0, 0};
int sup = cnt;
pair <int, int> ss[3] = {{sum[0], 0}, {sum[1], 1}, {sum[2], 2}};
sort(ss, ss + 3);
{
int z = max(min(ss[1].F - ss[0].F, sup), 0);
sup -= z;
ss[0].F += z;
d[ss[0].S] += z;
}
if (sup > 0)
{
int vvv = min(ss[2].F - ss[1].F, sup / 2);
sup -= vvv * 2;
ss[0].F += vvv;
ss[1].F += vvv;
d[ss[0].S] += vvv;
d[ss[1].S] += vvv;
if (sup == 1)
{
ss[0].F++;
d[ss[0].S]++;
--sup;
}
}
int ost = sup % 3;
sup /= 3;
d[0] += sup + (ost > 0);
--ost;
d[1] += sup + (ost > 0);
--ost;
d[2] += sup + (ost > 0);
for(int i = 0; i < d[0]; ++i)
answ[kek[i]] = 0;
for(int i = d[0]; i < d[0] + d[1]; ++i)
answ[kek[i]] = 1;
for(int i = d[0] + d[1]; i < cnt; ++i)
answ[kek[i]] = 2;
for(int i = 0; i < n; ++i)
cout << answ[i] + 1 << ' ';
return 0;
}
```
:::
## [4. Лабиринт Каталана](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2019_4)
:::spoiler Разбор
:::info
Пишем черепаху. На этом все!
Асимптотика: $O(N * M)$.
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
int a[1000][10000];
int dp[1000][10000];
int n, m;
int main() {
scanf("%i%i", &n, &m);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
scanf("%i", &a[i][j]);
dp[0][0] = 1;
for (int i = 1; i < n; ++i)
if (a[i][0] - a[i - 1][0] <= 1)
dp[i][0] = 1;
else break;
for (int i = 1; i < m; ++i)
if (a[0][i] - a[0][i - 1] <= 1)
dp[0][i] = 1;
else break;
for (int i = 1; i < n; ++i)
for (int j = 1; j < m; ++j) {
if (a[i][j] - a[i - 1][j] <= 1)
dp[i][j] += dp[i - 1][j];
dp[i][j] %= mod;
if (a[i][j] - a[i][j - 1] <= 1)
dp[i][j] += dp[i][j - 1];
dp[i][j] %= mod;
}
printf("%i", dp[n - 1][m - 1]);
return 0;
}
```
:::