【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

参考题解(官方):

【cf比赛记录】Codeforces Round #600 (Div. 2)

// 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;
}

记录我这菜鸟的成长经历

【cf比赛记录】Codeforces Round #600 (Div. 2)

上一篇:CF 600 D 题解


下一篇:webdriver 控制浏览器操作