Codeforces Round #842 (Div. 2)

Codeforces Round #842 (Div. 2)

https://codeforces.com/contest/1768

A. Greatest Convex

猜结论

#include <bits/stdc++.h>

using namespace std;

void solve () {
    int n;
    cin >> n;
    cout << n - 1 << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

B. Quick Sort

想了好久。
记录从1出发的最长上升序列长度 \(len\)(值中断就要断掉),答案就是 \((n-len+k-1)/k\)
因为把除了这一段之外的其它数字排好之后,这一段就会自动有序。

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 5;
int a[N], n, k;

void solve () {
    int ans = 0, pos = 0, len = 1;
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (a[i] == 1)     pos = i;
    }
    for (int i = pos + 1, k = 2; i <= n; i++) {
        if (a[i] == k)  len ++, k++;
    }
    //cout << cnt << ' ';
    cout << (n - len + k - 1) / k << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

//最长有序序列

C. Elemental Decompress

贪心。
贪心从小往大放。如果当前数字只出现一次,就可以让 \(p,q\) 都等于这个数字;如果当前数字出现两次,则一个放该数字,另一个放她对应的 \(set\) 里面最小值( \(set\) 里面存的是这个数组还没放的值)。看代码就很好懂啦!

#include <bits/stdc++.h>

using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
int cnt[N], p[N], q[N], n;
pii a[N];

void solve () {
    cin >> n;
    set<int> s1, s2;
    for (int i = 1; i <= n; i++)    cnt[i] = 0, s1.insert (i), s2.insert (i);
    for (int i = 1; i <= n; i++) {
        int x;  cin >> x;
        a[i] = {x, i};
        cnt[x] ++;
    }

    for (int i = 1; i <= n; i++) {
        if (cnt[i] > 2) {
            puts ("NO");
            return ;
        }
    }

    sort (a + 1, a + n + 1);
    for (int i = 1; i <= n; i++) {
        int val = a[i].first, pos = a[i].second;
        if (cnt[val] != 2) {
            p[pos] = q[pos] = val;
            s1.erase (val), s2.erase (val);
        }
        else {
            if (s1.count (val)) {
                if (*s2.begin () > val) {
                    puts ("NO");
                    return ;
                }
                p[pos] = val, q[pos] = *s2.begin ();
                s1.erase (val), s2.erase (s2.begin ());
            }
            else {
                if (*s1.begin () > val) {
                    puts ("NO");
                    return ;
                }
                q[pos] = val, p[pos] = *s1.begin ();
                s2.erase (val), s1.erase (s1.begin ());
            }
        }
    }
    puts ("YES");
    for (int i = 1; i <= n; i++)    cout << p[i] << ' ';  cout << endl;
    for (int i = 1; i <= n; i++)    cout << q[i] << ' ';  cout << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

//从小往大放

D. Lucky Permutation

结论题。
置换环结论: \(cnt\) 个环,变成排列所需次数为 \(n-cnt\),具体可以看 \(ygg\) 的题姐。
有序排列 \(\rightarrow\) 一个逆序对: 交换任意邻项 (本来需要 \(n-cnt+1\) 次,如果环中存在邻项的话就可以节省两次)

#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 5;
int a[N], n, cnt;
bool vis[N], exist;
set<int> s;

void dfs (int x) {
    if (vis[x])     return ;
    vis[x] = true;
    s.insert (x);
    if (s.count (x - 1) || s.count (x + 1))     exist = true;
    dfs (a[x]);
}

void solve () {
    cin >> n;
    cnt = 0, exist = false;
    for (int i = 1; i <= n; i++)    cin >> a[i], vis[i] = false;
    for (int i = 1; i <= n; i++) {
        if (vis[i])     continue;
        cnt ++, s.clear ();
        dfs (i);
    }
    int ans = n - cnt + 1;
    if (exist)  ans -= 2;
    cout << ans << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

//置换环结论: cnt个环,变成排列所需次数为n-cnt
//有序排列->一个逆序对: 交换任意邻项(本来是n-cnt+1,如果环中存在邻项的话就可以节省两次)
posted @ 2023-01-06 23:23  Sakana~  阅读(51)  评论(0编辑  收藏  举报