【cf比賽記錄】Codeforces Round #600 (Div. 2)


Codeforces Round #600 (Div. 2) ---- 比賽傳送門

昨晚成績還好,AC A,B題,還能上分(到底有多菜)

補了C、D題,因為昨晚對C、D題已經有想法了,所以補起題來也快。(C題TLE了,D題想用並查集沒好)

A

// http://codeforces.com/contest/1253/problem/A
/*
    如果YES,則b[i] - a[i] 在一個區間里的差肯定是相同的且不小於0
*/
#include<iostream>
#include<cstdio>
using namespace std;

int a[100005], b[100005];
int tar[100005];
int T, n, l, r, k;

int main()
{
    scanf("%d", &T);
    while(T--){
        bool flag = true;
        int pla = -1, num = 0, x = -1; // pla 來存儲第一個差不為 0 的位置 x 存第一個不為 0 的差值
        scanf("%d", &n);
        for(int i = 0; i < n; i++) scanf("%d", &a[i]);
        for(int i = 0; i < n; i++){
            scanf("%d", &b[i]);
            tar[i] = b[i] - a[i];
            if(tar[i] != 0) {
                if(pla == -1) { pla = i; x = tar[i]; } // 找到第一個 不等的點
                num++; // num 來記錄有多少個不同點
            }
        }

        if(pla == -1) printf("YES\n");
        else {
            for(int i = pla; i < n && num > 0; i++, num--){
                if(tar[i] != x){    // 一個個校對
                    flag = false;
                    break;
                }
            }
            if(x < 0) flag = false; // 特判第一個不等已經是 < 0 時
            if(flag) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

B

// http://codeforces.com/contest/1253/problem/B
/*
    因為分置的天數不需要最大或者最小,所以就直接處理最多天數的情況
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;

int num[1000006], c;
int in[1000006]; // 記錄員工是否已上班已下班,0表示沒上班,1表示還沒下班,2表示已經下班
int ans[1000006], ans_count;
int n, a, tot, num_c, ans_c;

int main()
{
    bool flag = true;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d", &a);
        if(a > 0){
            if(in[a] != 0) flag = false; // 如果已經上班了還上班,false
            else {  // 符合情況
                in[a]++;
                num[c++] = a;   // 記錄已經上班的員工
                tot += a;
            }
        }
        else {
            if(in[-a] != 1) flag = false; // 已經下班了或者還沒上班還下班,false
            else {          // 符合情況
                in[-a]++;
                tot += a;
            }
        }
        num_c++;
        if(tot == 0){   // tot == 0的時候既公司沒人的時候
            ans[ans_c++] = num_c;
            num_c = 0;
            for(int j = 0; j < c; j++){ // 初始化 用 memset 會超時
                in[num[j]] = 0;
            }
            c = 0; // 初始化
        }
    }
    if(n & 1) flag = false;     // 特判 n 為奇數時
    if(tot != 0) flag = false;  // 特判最后一天 tot != 0 即公司的員工有人還沒下班
    if(flag){                   // 符合情況 輸出答案
        printf("%d\n", ans_c);
        for(int i = 0; i < ans_c; i++){
            printf("%d%c", ans[i], i == ans_c - 1 ? '\n' : ' ');
        }
    }
    else printf("-1\n");        // 不符合情況時輸出 -1

    return 0;
}

C

參考題解(官方):

// http://codeforces.com/contest/1253/problem/C
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

int n, m;
int sweet[200005];
long long ans[200005];

// 前綴和 O(nlogn) ---- 主要用在了排序
int main(){
    scanf("%d %d", &n, &m);

    for(int i = 1; i <= n; i++) scanf("%d", &sweet[i]);
    sort(sweet + 1, sweet + n + 1);

    long long tot = 0;
    for(int i = 1; i <= n; i++){
        tot += sweet[i];
        ans[i] = tot;
        if(i > m){      // 當吃的比m大的時候,只是比 i - m 一天多了個 ans[i - m](可以在紙上寫寫)
            ans[i] += ans[i - m];   // 前綴和
        }
        printf("%I64d%c", ans[i], i == n ? '\n' : ' ');
    }

    return 0;
}

/* O(n^2) TLE
int main()
{
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        scanf("%d", &sweet[i]);
    }
    sort(sweet, sweet + n);

    double M = m;

    for(int i = 1; i <= n; i++){
        int day = ceil(i / M);
        int eat = i;
        int day_can = m;
        int day_s = 1;
        long long tot = 0;
        while(eat > 0){     // 模擬操作
            tot += sweet[eat - 1] * day_s;
//            printf("tot:%I64d sweet:%d day_s:%d can:%d\n", tot, sweet[eat - 1], day_s, day_can);
            day_can--;
            if(day_can == 0){
                day_s++;
                day_can = m;
            }
            eat--;
        }
//        printf("\n");
        ans[i] = tot;
//        printf("day:%d\n", day);
    }
    for(int i = 0; i < n; i++){
        printf("%d%c", sweet[i], i == n - 1 ? '\n' : ' ');
    }
    for(int i = 1; i <= n; i++){
        printf("%I64d%c", ans[i], i == n ? '\n' : ' ');
    }

    return 0;
}
*/

D

參考題解的出處在代碼里

// http://codeforces.com/contest/1253/problem/D
// 參考:Marca 的 #65186644 的 AC 代碼
#include<iostream>
#include<cstdio>
using namespace std;

int n, m, a, b, x, y, ans;
int par[200005];

void init(int n){
    for(int i = 1; i <= n; i++) par[i] = i;
}

int ff(int x){
    if(par[x] == x) return x;
    else return par[x] = ff(par[x]);
}

// 並查集解法
int main()
{
    scanf("%d %d", &n, &m);
    init(n);
    for(int i = 0; i < m; i++){
        scanf("%d %d", &a, &b);
        x = ff(a);
        y = ff(b);
        // 把點大的都做樹的根節點
        if(x > y) swap(x, y);
        par[x] = y;
    }

    for(int i = 1; i <= n; i++){
        x = ff(i);      // ff函數已包含路徑壓縮
        while(i < x){
            y = ff(i);
            if(x != y){ // 不在一個區間里 合並
                ans++;  // 路徑 ++
                // 把點大的做樹的根節點
                if(y > x) swap(x, y);
                par[y] = x;
            }
            i++;
        }
    }

    printf("%d\n", ans);

    return 0;
}

記錄我這菜鳥的成長經歷


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM