---
# System prepended metadata

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

---

# Разбор задач 2021 года
:::warning
Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя!
:::

## 1. Простые соседних интервалов
:::spoiler Разбор
:::info
Давайте забинарим ответ. И теперь для каждого отрезка длины mid проверим, содержит ли он как минимум $K$ простых чисел. Это можно делать эффективно предпрощитав зарание массив преффиксов $pref_i$ - количество простых чисел на отрезке $[1..i]$ и при проверке в бинарном поиске за $О(n)$ проверим на корректность каждый отрезок. 
:::

:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define pb push_back
#define F first
#define S second
#define ll long long
#define ull unsigned long long
#define ld long double
#define endl '\n'
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int , int >
#define Endl '\n'

#pragma GCC optimize("Ofast")

using namespace std;
using namespace __gnu_pbds;


template <typename T>
using ordered_set = tree <T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

mt19937 gen(chrono::system_clock::now().time_since_epoch().count());

const int mod = 1e9 + 7;

const int SX[4] = {0 , 1 , -1 , 0};
const int SY[4] = {1 , 0 , 0 , -1};
const int rx[8] = {1, -1, 0, 0, 1, 1, -1, -1};
const int ry[8] = {0, 0, 1, -1, 1, -1, 1, -1};
const int kx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
const int ky[8] = {2, -2, 2, -2, 1, -1, 1, -1};

typedef cc_hash_table< int, int, hash<int>, equal_to<int>, direct_mask_range_hashing<int>, hash_standard_resize_policy<hash_exponential_size_policy<>, hash_load_check_resize_trigger<true>, true>> ht;

int32_t main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#else
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    int a, b, k;
    cin >> a >> b >> k;
    int ans = 1e9;
    vector < int > pref(b + 1);
    pref[0] = 0;
    pref[1] = 0;
    for (int i = 2;i <= b; ++i){
        bool ok = 1;
        for (int d = 2;d * d <= i; ++d){
            if (i % d == 0){
                ok = 0;
                break;
            }
        }
        pref[i] = pref[i - 1] + ok;
    }
    int ot = -1;
    int l = 1, r = b - a + 1;
    while(l <= r){
        int mid = (l + r) >> 1;
        bool ok = 1;
        for (int i = a;i + mid - 1 <= b; ++i){
            if (pref[i + mid - 1] - pref[i - 1] >= k)continue;
            ok = 0;
            break;
        }
        if (ok)r = mid - 1, ot = mid;
        else l = mid + 1;
    }
    cout << ot << endl;
    return 0;
}

```
:::

## [2. Минимумы в перестановке](https://codeforces.com/group/skz9fIV5Hq/contest/321564/problem/B)
:::spoiler Разбор
:::info
Давайте решим данную задачу для $N \leq 7$ и сделаем некоторые замечания:

1. Количество последовательностей, котоорые нам подходят под условия задачи $(N - 1) ^ 2$.
2. Три числа $N$, $N - 1$, $N - 2$ постоянно находятся "рядом" друг с другом.

Вот 4 случая расположения этих 3-х чисел:
```cpp
    // 1
    all[0][0] = n - 2;
    all[0][1] = n - 1;
    all[0][2] = n;
 
    // 2
    all[1][0] = n - 2;
    all[1][1] = n;
    all[1][2] = n - 1;
 
    // 3
    all[2][0] = n - 1;
    all[2][1] = n;
    all[2][2] = n - 2;
 
    // 4
    all[3][0] = n;
    all[3][1] = n - 1;
    all[3][2] = n - 2;
```

Доказательстов, почему это так происходит, оставим как домашнее задание.

3. Эти три числа двигаются от конца к началу.

1 2 3 [4 5 6] 
1 2 3 [4 6 5] 
1 2 3 [5 6 4] 
1 2 3 [6 5 4] 
1 2 [4 5 6] 3 
1 2 [4 6 5] 3 
1 2 [5 6 4] 3 
1 2 [6 5 4] 3 
...
1 [4 5 6] 3 2 
1 [4 6 5] 3 2 
1 [5 6 4] 3 2 
1 [6 5 4] 3 2 

4. Давайте рассмотрим больший пример и придумаем конструктор.
5. Давайте научимся определять последний элемент.
6. Заведем множество чисел, в которое будут входить числа от [1 до N - 3].
7. Давайте заметим, что количество последовательностей, которые заканчиваются на 

$N - 3$ - 4 шт.
$N - 4$ - 8 шт.
$N - 5$ - 16 шт.

8. Давате вычтем из K -= $2^x$, где $x$ - максимальная степень двойки, которая строго меньше K. Текущий элемент последовательности это (x - 2)-ый элемент по убыванию, из множества чисел. Поставили число, затем удалили его из множества. 
9. Крайний случай, когда K <= 4. Разберем его отдельно.


:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define pb push_back
#define F first
#define S second
#define ll long long
#define ull unsigned long long
#define ld long double
#define endl '\n'
#define TIME 1.0*clock()/CLOCKS_PER_SEC
#define pii pair < int , int >
#define Endl '\n'

#pragma GCC optimize("Ofast")

using namespace std;
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree <T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

mt19937 gen(chrono::system_clock::now().time_since_epoch().count());

const int mod = 1e9 + 7;

const int SX[4] = {0 , 1 , -1 , 0};
const int SY[4] = {1 , 0 , 0 , -1};
const int rx[8] = {1, -1, 0, 0, 1, 1, -1, -1};
const int ry[8] = {0, 0, 1, -1, 1, -1, 1, -1};
const int kx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
const int ky[8] = {2, -2, 2, -2, 1, -1, 1, -1};

typedef cc_hash_table< int, int, hash<int>, equal_to<int>, direct_mask_range_hashing<int>, hash_standard_resize_policy<hash_exponential_size_policy<>, hash_load_check_resize_trigger<true>, true>> ht;

void solve(){
    ll n, k;
    cin >> n >> k;
    if (n == 1){
        cout << 1 << endl;
        return;
    }
    if (n == 2){
        if (k == 1)cout << "1 2" << endl;
        else cout << "2 1" << endl;
        return;
    }
    int all[4][3];
    // 1
    all[0][0] = n - 2;
    all[0][1] = n - 1;
    all[0][2] = n;

    // 2
    all[1][0] = n - 2;
    all[1][1] = n;
    all[1][2] = n - 1;

    // 3
    all[2][0] = n - 1;
    all[2][1] = n;
    all[2][2] = n - 2;

    // 4
    all[3][0] = n;
    all[3][1] = n - 1;
    all[3][2] = n - 2;

    int ans[n];
    set < int > st;
    for (int i = 0;i < n; ++i)st.insert(i + 1);
    st.erase(n);
    st.erase(n - 1);
    st.erase(n - 2);

    int pos = n - 1;
    while(k){
        if (k <= 4){
            int mem = 0;
            for (int i = 0;i <= pos; ++i){
                if (st.size()){
                    ans[i] = *st.begin();
                    st.erase(ans[i]);
                }else{
                    ans[i] = all[k - 1][mem];
                    mem++;
                }
            }
            k = 0;
            continue;
        }
        ll kol = 4;
        int p = 0;
        while(k - kol * 2 > 0)kol *= 2, p++;
        k -= kol;
        vector < int > lol;
        for (auto to : st)lol.pb(to);
        for (int i = 0;i < p; ++i)lol.pop_back();
        ans[pos] = lol.back();
        st.erase(lol.back());
        pos--;
    }

    for (auto to : ans)cout << to << " ";
    cout << endl;
}

int32_t main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#else
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    int t;
    cin >> t;
    while(t --> 0)solve();
    return 0;
}
```
:::

## [3. Самый длинный слог](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2016_3)
:::spoiler Разбор
:::info
Это очень запарная и неприятная реализация. Разбираем все случаи (они описаны в условии). Выводим ответ.

Асимптотика: $O(N + |allS|)$, где $|allS|$ -- длина всех строк.
:::

:::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun))
```cpp
#include <bits/stdc++.h>
using namespace std;

vector<string> w;

int main() {
    string s;

    getline(cin,s);
    string cur = "";
    for (int i = 0; i < s.size(); i++)
        if (s[i] == ' ') {
            w.push_back(cur);
            cur = "";
        } else cur += s[i];
    if (cur != "")
        w.push_back(cur);

    int ma=0;
    string ans;

    for (int i = 0; i < w.size(); i++) {
        vector<int> gl;
        int pr = -1;
        for (int j = 0; j < w[i].size(); j++)
            if (w[i][j]=='a' || w[i][j]=='e' || w[i][j]=='y' || w[i][j]=='i' || w[i][j]=='o' || w[i][j]=='u')
                gl.pb(j);
        int cur = 0;
        string t;

        for (int j = 0; j < w[i].size(); j++)
            if (cur == 0 && j < gl[0])
                t += w[i][j];
            else if(cur == gl.size()-1 && j >= gl[cur])
                t+=w[i][j];
            else if (gl[cur] == j && cur != gl.size()-1) {
                t += w[i][j];
                cur++;
                if (gl[cur] - gl[cur-1] <= 2 || w[i][j] == 'y') {
                    if (t.size() > ma) {
                        ans = t;
                        ma = t.size();
                    }
                    t = "";
                }
            } else if (gl[cur-1] == j-1) {
                t += w[i][j];
                if (t.size()>1) {
                    if (t.size() > ma) {
                        ans = t;
                        ma = t.size();
                    }
                    t = "";
                }
            } else t+=w[i][j];

        if(t != "") {
            if (t.size() > ma) {
                ans = t;
                ma = t.size();
            }
            t = "";
        }
    }

    cout << ans << endl;
}
```
:::

## [4. Пессимистичный прогноз](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2016_4)
:::spoiler Разбор
:::info
Давайте напишем жадный алгоритм. Вначале отсортируем все команды по рейтингу (он описан в условии). Теперь все команды, которые выше $k$-й, мы трогать не будем (выдавать медали). Оставшимся командам будем жадно выдавать медали по следующему алгоритму:
1. Пытаемся выдать на $1$ бронзовую медаль больше, чем у $k$-й (если можем), при этом уравниваем количество золотых и серебрянных медалей.
2. Пытаемся выдать на $1$ серебрянную медаль больше, чем у $k$-й (если можем), при этом уравниваем количество золотых медалей.
3. Пытаемся выдать на $1$ золотую медаль больше чем у $k$-й (если можем).

Асимптотика решения: $O(N * log(N))$.
:::

:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;

struct node {
    int Gold, Silver, Bronze;
    int id;
    node() {
        Gold = 0;
        Silver = 0;
        Bronze = 0;
        id = -1;
    }
    bool operator < (const node &x) {
        if (x.Gold != Gold) return x.Gold > Gold;
        else if (x.Silver != Silver) return x.Silver > Silver;
        else return x.Bronze > Bronze;
    }
};

vector<node> all;

int kol_Gold = 0;
int kol_Silver = 0;
int kol_Bronze = 0;

int main() {
    int n, k;
    cin >> n >> k >> kol_Gold >> kol_Silver >> kol_Bronze;
    all.resize(n);
    for (int i = 0; i < n; ++i) {
        cin >> all[i].Gold >> all[i].Silver >> all[i].Bronze;
        all[i].id = i + 1;
    }
    sort(all.rbegin(), all.rend());
    int ans = 0;
    bool ok = 1;
    node Team;
    for (int i = 0; i < n; ++i) {
        if (all[i].id != k && ok) {
            ans++;
            continue;
        }
        if (all[i].id == k) {
            ok = 0;
            Team = all[i];
            continue;
        }
        int need_Gold = -all[i].Gold + Team.Gold;
        int need_Silver = -all[i].Silver + Team.Silver;
        int need_Bronze = -all[i].Bronze + Team.Bronze;
        if (need_Gold <= kol_Gold && need_Silver <= kol_Silver && need_Bronze + 1 <= kol_Bronze) {
            kol_Gold -= (need_Gold < 0 ? 0 : need_Gold);
            kol_Silver -= (need_Silver < 0 ? 0 : need_Silver);
            kol_Bronze -= (need_Bronze >= 0 ? need_Bronze + 1 : 0);
            ans++;
            continue;
        }
        if (need_Gold <= kol_Gold && need_Silver + 1 < kol_Silver) {
            kol_Gold -= (need_Gold < 0 ? 0 : need_Gold);
            kol_Silver -= (need_Silver >= 0 ? need_Silver + 1 : 0);
            ans++;
            continue;
        }
        if (need_Gold + 1 <= kol_Gold) {
            kol_Gold -= (need_Gold >= 0 ? need_Gold + 1 : 0);
            ans++;
            continue;
        }
    }
    cout << ans << endl;
    return 0;
}
```
:::