1. 程式人生 > 其它 >Codeforces Round #792 (Div. 1 + Div. 2) A—D

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

沒做出來,貼上官方題解:


故令\(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
出錯的點在於,
(我還沒找到到,一會兒再回來改吧)
錯誤程式碼:

#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次,變成列非減
//求逆序對數量
//整列交換

//找到就交換

D. Traps

貪心,擺個大佬的證明:

#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個
//注意傷害可疊加

//有點像能量石