Codeforces Round #792 (Div. 1 + Div. 2) A—D

Codeforces Round #792 (Div. 1 + Div. 2)

https://codeforces.com/contest/1684

A. Digit Minimization

特判两位数的情况(答案只能为个位数),其余的只需要找出最小的那个数字即可

#include <bits/stdc++.h>

using namespace std;

int main () {
    int t;
    cin >> t;
    while (t --) {
        int n;
        cin >> n;
        if (n < 100) {
            cout << n % 10 << endl;
            continue;
        }
        //min
        int x = 9;
        while (n) {
            x = min (x, n % 10);
            n /= 10;
        }
        cout << x << endl;
    }
}

B. Z mod X = C

没做出来,贴上官方题解:

image
故令\(x = a + b + c, y = b + c, z = c\)即可

真没想到要这么构造,只能说多练吧emm

#include <bits/stdc++.h>

using namespace std;

int main () {
    int t;
    cin >> t;
    while (t --) {
        long long a, b, c;
        cin >> a >> b >> c;
        cout << a + b + c << ' ' << b + c << ' ' << c << endl;
    }
}
//这构造实在是想不到

C. Column Swapping

一开始读错题目了,看成列的非降(英语太差emmm)
后来的想法是求每行的逆序对,然后如果某一行的逆序对数量大于1就直接不可能。如果等于1就看别的行的逆序对是不是也在这个位置上。注意的是再判断一下原本就有序的其他行,在交换后合不合理。(判断方法:比较这两处的大小,\(a_x \geq a_y\)就合理。
(但是我没整出来,可能是代码能力太弱了)

后来又换了一种做法,就是直接交换每两行的任意逆序位置(即从两头开始找,找到就交换),但是也做错了。。
错误:分case没问题,合在一起就输出全为1 1
出错的点在于,每一次开新cases的时候没有初始化,而且这么找也不太对(没法完全有序)
错误代码:

#include <bits/stdc++.h>

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

struct Node {
    int hang, x, y;
}ans [N];


void find (int x) {
    for (int i = 1, j = m; i < j; i ++, j --) {
        if (a[x][i] > a[x][j]) {
            ans[cnt ++] = {x, i, j};
            break;
        }
    }
}

void test () {
    for (int i = 0; i < cnt; i  ++)
        cout << i << ": " << ans[i].hang << ' ' << ans[i].x << ' ' << ans[i].y << endl;
}

void solve () {
        
        cin >> n >> m;
        for (int i = 1; i <= n; i ++) {
            a[i].push_back (0);
            for (int j = 1; j <= m; j ++) {
                int t;
                cin >> t;
                a[i].push_back (t);
            }
            find (i);
        }

        if (cnt == 0) {
            cout << 1 << ' ' << 1 << endl;
            return ;
        }

        //test ();

        if (cnt == 1) {
            for (int i = 1; i <= n; i ++) {
                if (i == ans[0].hang)
                    continue;
                int xx = ans[0].x, yy = ans[0].y;
                if (a[i][xx] < a[i][yy]) {
                    cout << -1 << endl;
                    return ;
                }
                else {
                    cout << xx << ' ' << yy << endl;
                    return ;
                }
            }
        }

        bool flag = true;
        for (int i = 1; i < cnt; i ++) {
            if (ans[i].x != ans[i - 1].x || ans[i].y != ans[i - 1].y) {
                flag = false;
                break;
            }
        }
        if (flag)
            cout << ans[0].x << ' ' << ans[0].y << endl;
        else   
            cout << -1 << endl;

        
        
}

int main () {
    int t;
    cin >> t;
    while (t --) {
        cnt = 0;
        solve ();

    }
}
//只交换两个<=1次,变成列非减
//求逆序对数量
//整列交换

//找到就交换

正确代码
就该用is_sorted 按行来判断

#include <bits/stdc++.h>

using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;

int cnt;
int n, m;

void solve () {
    cin >> n >> m;
    vector <vector <int>> a(n, vector<int>(m)), b(n, vector<int>(m));   
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < m; j ++) {
            cin >> a[i][j], b[i][j] = a[i][j];
            //a[i].push_back (t), b[i].push_back (t);
        }

    for (int i = 0; i < n; i ++)
        sort (b[i].begin (), b[i].end());

    //锁定要交换的两列
    int x = -1, y = -1;
    bool find = false;
    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < m; j ++) {
            if (a[i][j] != b[i][j]) {
                if (x == -1)    x = j, find = true;
                else if (y == -1)    y = j; //x更新完了,才更新y
            }
        }
        if (find)    break;
    }

    if (x == -1) //没更新
        x = y = 0;
    for (int i = 0; i < n; i ++)
        swap (a[i][x], a[i][y]);
    
    bool flag = true;
    for (int i = 0; i < n; i ++)
        if (!is_sorted (a[i].begin (), a[i].end ())) {
            flag = false;
            break;
        }
    if (flag)   cout << x + 1 << ' ' << y + 1 << endl; //偏移
    else    cout << -1 << endl;
          
}

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

    }
}
//每一行都排一下序,然后看看符合不

D. Traps

贪心,摆个大佬的证明:

image

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 2e5 + 5;

int n, k;
ll a[N];
bool skip[N]; //是否需要跳过
pii b[N]; //a_i+i(用于排序),second记录下标

void solve () {
    memset (skip, false, sizeof skip);
    ll ans = 0;
    cin >> n >> k;

    for (int i = 1; i <= n; i++)
        cin >> a[i], b[i].first = a[i] + i, b[i].second = i;
    
    if (n == k) {
        cout << 0 << endl;
        return ;
    }

    sort (b + 1, b + n + 1, greater <pii> ());

    for (int i = 1; i <= k; i ++)
        skip[b[i].second] = true; //前k大的需要skip

    ll d = 0; //叠加量
    for (int i = 1; i <= n; i ++) {
        if (skip[i])
            d ++;
        else
            ans += a[i] + d;
    }
    
    cout << ans << endl;
}

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

}

//每个点的价值相当于a_i+i,然后排序,去掉前k个
//注意伤害可叠加

//有点像能量石
posted @ 2022-05-20 10:45  Sakana~  阅读(93)  评论(0编辑  收藏  举报