# Разбор задач 2014 года
Если Вы не знали как решать какую-то задачу и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас.
:::warning
Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя!
:::
## [1. Парк аттракционов](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2014_1)
:::spoiler Разбор
:::info
Давайте посчитаем два массива $pref_i$ -- минимальное количество земли, которую надо убрать, чтобы все высоты от $1$-й до $i$-й шли по неубыванию, и $suff_i$ -- минимальное количество земли, которую надо убрать, чтобы все высоты от $i$-й до $n$-й шли по невозрастанию.
Тогда ответ будет такой: $ans = min(ans, pref_i + suff_i)$ для всех $i$ от $1$ до $n$.
Теперь осталось разобрать, как считать $pref_i$ и $suff_i$.
Давайте введём понятие **ступенек** -- это подряд идущие и одиннаковые по высоте горы, в формате *{высота ступеньки, длина ступеньки}*. Например, во множестве $\{1, 1, 1, 3, 4, 4, 4\}$ ступеньки будут выглядеть так: $\{1, 3\}$, $\{3, 1\}$, $\{4, 3\}$.
Основная идея заключается в том, что если мы встретили гору, которая ниже предыдущей, то нам всегда выгодно "срезать" все предыдущие горы под уровень нашей текущей горы.
Давайте поддерживать очередь, в которой будем хранить ступеньки. Будем иттерироваться от $1$ до $n$ и считать $pref_i$. У нас есть 2 случая:
1. Если текущая гора выше предыдущей, мы добавляем очередную ступеньку;
2. Если текущая гора ниже предыдущей, мы "срезаем" все предыдущие горы, которые выше нашей текущей. Тем сасмым у нас образуется ступенька.
Аналогично считаем $suff_i$.
Асимптотика: $O(N)$.
:::
:::spoiler Авторское решение (С++)
```cpp
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
int a[100005];
long long f[100005];
long long g[100005];
int q[100005];
int qcount[100005];
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
f[0] = 0;
int uk = 1;
q[0] = a[0];
qcount[0] = 1;
for (int i = 1; i < n; ++i) {
f[i] = f[i-1];
int count = 0;
while (uk > 0 && a[i] <= q[uk-1]) {
f[i] += 1ll * (q[uk-1] - a[i]) * qcount[uk-1];
count += qcount[uk-1];
--uk;
}
q[uk] = a[i];
qcount[uk] = 1 + count;
uk++;
}
g[n-1] = 0;
uk = 1;
q[0] = a[n-1];
qcount[0] = 1;
for (int i = n-2; i >= 0; --i) {
g[i] = g[i+1];
int count = 0;
while (uk > 0 && a[i] <= q[uk-1]) {
g[i] += 1ll * (q[uk-1] - a[i]) * qcount[uk-1];
count += qcount[uk-1];
--uk;
}
q[uk] = a[i];
qcount[uk] = 1 + count;
uk++;
}
long long minimum = 1ll<<60;
int peak = n;
for (int i = 0; i < n; ++i) {
if (f[i] + g[i] < minimum) {
minimum = f[i] + g[i];
peak = i + 1;
}
}
cout << peak << " " << minimum << endl;
return 0;
}
```
:::
:::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 (auto &to : a) cin >> to;
vector<pair<int, int>> q;
long long pref[n];
pref[0] = 0;
q.push_back({a[0], 1});
for (int i = 1; i < n; ++i) {
pref[i] = pref[i - 1];
int kol = 0;
while (q.size() && q[q.size() - 1].first >= a[i]) {
pref[i] += (long long)(q[q.size() - 1].first - a[i]) * q[q.size() - 1].second;
kol += q[q.size() - 1].second;
q.pop_back();
}
q.push_back({a[i], kol + 1});
}
q.clear();
long long suf[n];
suf[n - 1] = 0;
q.push_back({a[n - 1], 1});
for (int i = n - 2; i >= 0; --i) {
suf[i] = suf[i + 1];
int kol = 0;
while (q.size() && q[q.size() - 1].first >= a[i]){
suf[i] += (long long)(q[q.size() - 1].first - a[i]) * q[q.size() - 1].second;
kol += q[q.size() - 1].second;
q.pop_back();
}
q.push_back({a[i], kol + 1});
}
int pos = -1;
long long mi = 1e18;
for (int i = 0; i < n; ++i)
if (pref[i] + suf[i] < mi)
mi = pref[i] + suf[i], pos = i + 1;
cout << pos << " " << mi << endl;
return 0;
}
```
:::
## [2. Красивая задача](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2014_2)
:::spoiler Разбор
:::info
Делаем ровно то, что просят в условии. Находим количество делителей за корень.
Асимптотика: $O(\sqrt{N})$.
:::
:::spoiler Авторское решение (C++)
```cpp
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;
int a[1000005];
int b[1000005];
int main() {
int n, nn;
cin >> n;
nn = n;
int k = 0;
int d = 2;
while ((1ll*d)*d <= n) {
if (n%d == 0) {
a[k] = d;
b[k] = 0;
while (n%d == 0) {
n/=d;
++b[k];
}
++k;
}
if (d == 2) ++d;
else d += 2;
}
if (n > 1) {
a[k] = n;
b[k] = 1;
++k;
}
int m = 1;
for (int i = 0; i < k; ++i) {
m *= b[i] + 1;
}
if (nn%m == 0)
cout << "Yes " << (nn/m) << endl;
else
cout << "No " << (nn%m) << endl;
return 0;
}
```
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int a;
cin >> a;
int kol = 0;
int d = 1;
while (d * d < a) {
if (a % d == 0) kol += 2;
d++;
}
if (d * d == a) kol++;
if (a % kol == 0)
cout << "Yes " << a / kol << endl;
else cout << "No " << a % kol << endl;
return 0;
}
```
:::
## [3. Плагиат](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2014_3)
:::spoiler Разбор
:::info
Давайте напишем [НОП](https://ru.m.wikipedia.org/wiki/%D0%9D%D0%B0%D0%B8%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B0%D1%8F_%D0%BE%D0%B1%D1%89%D0%B0%D1%8F_%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0#:~:text=%D0%9D%D0%B0%D0%B8%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B0%D1%8F%20%D0%BE%D0%B1%D1%89%D0%B0%D1%8F%20%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0%20%D0%B0%D0%BD%D0%B3%D0%BB.,%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%2C%20%D0%B8%D0%BC%D0%B5%D1%8E%D1%89%D0%B0%D1%8F%20%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D1%83%D1%8E%20%D0%B4%D0%BB%D0%B8%D0%BD%D1%83). На этом все!
Асимптотика: $O(N^2)$.
:::
:::spoiler Авторское решение (C++)
```cpp
#include <iostream>
#include <stdio.h>
#include <locale>
#include <map>
#include <algorithm>
#include <math.h>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
string olds, news;
map <string, int> dictionary;
map <int, string> bdictionary;
int num = 0, olen, nlen;
vector <int> oldw, neww;
int parce(string s, vector <int> & v) {
int l = 0;
string word = "";
s += ' ';
for (int i = 0; i < s.length(); ++i){
if (s[i] == ' ') {
if (!dictionary.count(word)){
++num;
dictionary[word] = num;
bdictionary[num] = word;
}
v[l] = dictionary[word];
++l;
word = "";
continue;
}
word += s[i];
}
return l;
}
int main() {
getline(cin, olds);
getline(cin, news);
oldw.resize(olds.length());
neww.resize(news.length());
olen = parce(olds, oldw);
nlen = parce(news, neww);
vector < vector <int> > lcs;
lcs.resize(olen+1);
for (int i = 0 ; i < olen+1; ++i)
lcs[i].resize(nlen);
if (oldw[0] == neww[0]) lcs[0][0] = 1;
else lcs[0][0] = 0;
for (int i = 1; i < nlen; ++i)
if (oldw[0] == neww[i]) lcs[0][i] = lcs[0][i-1] + 1;
else lcs[0][i] = 0;
for (int i = 1; i < olen; ++i)
if (oldw[i] == neww[0]) lcs[i][0] = lcs[i-1][0] + 1;
else lcs[i][0] = 0;
for (int i = 1; i < olen; ++i) {
for (int j = 1; j < nlen; ++j) {
if (oldw[i] == neww[j]) lcs[i][j] = lcs[i-1][j-1] + 1;
else lcs[i][j] = 0;
}
}
int maxlen = 0, maxj = 0;
for (int i = 0; i < olen; ++i) {
for (int j = 0; j < nlen; ++j) {
if (lcs[i][j] > maxlen) {
maxlen = lcs[i][j];
maxj = j;
}
}
}
if (maxlen <= nlen/2) {
cout << "No\n";
return 0;
}
cout << "Yes\n";
maxj -= maxlen - 1;
for (int i = maxj; i < maxj + maxlen; ++i)
cout << bdictionary[neww[i]] << " ";
cout << endl;
return 0;
}
```
:::
:::spoiler Код (C++, автор: [BaluconisTima](https://codeforces.com/profile/BaluconisTima))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
long long n, m;
string s1, s2;
getline(cin, s1);
getline(cin, s2);
vector<string> s, ss;
s.push_back("@");
ss.push_back("!");
long long j = 0;
s1 = s1 + ' ';
s2 = s2 + ' ';
for (int i = 0; i < int(s1.size()); i++) {
if (s1[i] == ' ' || i - 1 == int(s1.size())) {
s.push_back(s1.substr(j,i - j));
j = i + 1;
}
}
j = 0;
for (int i = 0; i < int(s2.size()); i++) {
if (s2[i] == ' '|| i - 1== int(s2.size())) {
ss.push_back(s2.substr(j,i - j));
j = i + 1;
}
}
s1 = "";
s2 = "";
n = int(s.size());
m = int(ss.size());
pair<long long, long long> p;
long long ma = 0;
vector<vector<int>> dp(n, vector<int>(m, 0));
for (int i = 1; i < n; i++)
for (int j = 1; j < m; j++) {
if (s[i] == ss[j])
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > ma) {
ma = dp[i][j];
p = {i, j};
}
}
if (ma > ((m - 1) / 2)) {
cout << "Yes" << endl;
ma--;
p = {p.first - ma, p.second - ma};
for(int i = 0; i <= ma; i++)
cout << s[p.first + i] << ' ';
cout << endl;
} else cout << "No" << endl;
}
```
:::
## [4. Автомобильный салон](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2014_4)
:::spoiler Разбор
:::info
Давайте **<ins>[отсортируем](https://habr.com/ru/post/335920/)</ins>** уникальные числа и выведем $k$-е.
Асимптотика: $O(N * log(N))$.
:::
:::spoiler Авторское решение (C++)
```cpp
#include <algorithm>
#include <math.h>
#include <iostream>
#include <cstdio>
using namespace std;
bool comp (int i, int j) {
return i > j;
}
int a[1000005];
int main() {
int n, k;
cin >> n >> k;
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
sort(a, a+n, comp);
if (k == 1) {
cout << a[0] << endl;
return 0;
}
int t=1;
for (int i = 1; i < n; ++i) {
if(a[i] != a[i-1]){
t++;
if (t==k){
cout << a[i] << endl;
return 0;
}
}
}
cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
return 0;
}
```
:::
:::spoiler Код (C++, автор: [gruntov_dima](https://codeforces.com/profile/gruntov_dima))
```cpp
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree <int,null_type,greater<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
int main() {
vector<string> v1;
long long n,k;
cin >> n >> k;
ordered_set st;
for (int i = 0; i < n; i++) {
long long x;
cin >> x;
st.insert(x);
}
cout << *st.find_by_order(k-1) << endl;
return 0;
}
```
:::
## [5. Подготовка](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2014_5)
:::spoiler Разбор
:::info
Делаем ровно то, что просят в условии. Это будет работать быстро, так как $N \leq 10^5$.
Асимптотика: $O(N)$.
:::
:::spoiler Авторское решение (C++)
```cpp
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int n, x, y;
scanf("%d%d%d", &n, &x, &y);
int days = 0, solved = 0;
while (solved < n) {
solved += x;
x += y;
++days;
}
printf("%d\n", days);
return 0;
}
```
:::
:::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
long long n, x, y;
cin >> n >> x >> y;
long long ans = 0;
long long kol = x;
while (n > 0) {
n -= kol;
kol += y;
ans++;
}
cout << ans << endl;
return 0;
}
```
:::