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