[Cf game record] Codeforces Round # 604 (Div. 2)

Game portal

This feeling is most easily done since the last of a continuous upper, happy w

A first three questions, then the fourth question in fact there are more than half an hour, but the fear of the body barely holding on, then back, in fact, the fourth question is also very simple

Think of the algorithm Tags:

A. violence simulation, string

B. mathematics, construction, sorting

C. greedy, construction

D. structure, traversal

:D

A. Beautiful String

// https://codeforces.com/contest/1265/problem/A
/*
    要求:不能有连续相同的字符,然后把'?'改为'a' || 'b' || 'c',使最终字符串符合要求
        如果不满足就 '-1'

    -1 好办 ---- 如果原字符串里就不符合就为 -1
    我的做法是暴力模拟 ( 暴力的意思是代码有点长...然后自己 wa 了两发 tcl )
*/
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;

int T;
string a;
bool A, B, C;

int main()
{
    cin >> T;
    while(T--){
        cin >> a;
        A = B = C = false;

        bool ok = true; // 判断是否 -1
        int j = 0;

        for(int i = 1; i < a.size(); i++){
            if(a[i] == a[i - 1] && a[i] != '?'){
                ok = false; // 是 -1
                break;
            }
        }

        if(a.size() > 1 && ok){ // 长度超过 1 且 原字符串没有问题的情况
            // 特判第一位
            if(a[0] == '?'){
                if(a[1] == 'a') A = true;
                else if(a[1] == 'b') B = true;
                else if(a[1] == 'c') C = true;
                else if(a[1] == '?') a[0] = 'a';

                if(A) a[0] = 'b';
                else if(B) a[0] = 'c';
                else if(C) a[0] = 'a';
            }

            A = B = C = false;
            // 特判最后一位
            if(a[a.size() - 1] == '?'){
                if(a[a.size() - 2] == 'a') A = true;
                else if(a[a.size() - 2] == 'b') B = true;
                else if(a[a.size() - 2] == 'c') C = true;
                else if(a[a.size() - 2] == '?') a[a.size() - 1] = 'a';

                if(A) a[a.size() - 1] = 'b';
                else if(B) a[a.size() - 1] = 'c';
                else if(C) a[a.size() - 1] = 'a';
            }

            for(int i = 1; i < a.size() - 1; i++){ // 对 (1, size() - 1) 开始暴力搜索
                A = B = C = false; // 记录前后出现了哪个字符
                if(a[i - 1] == 'a') A = true;
                else if(a[i - 1] == 'b') B = true;
                else if(a[i - 1] == 'c') C = true;

                if(a[i + 1] == 'a') A = true;
                else if(a[i + 1] == 'b') B = true;
                else if(a[i + 1] == 'c') C = true;

                if(a[i] == '?'){ // 只需要改 '?'
                    if(A && B) a[i] = 'c';
                    else if(A && C) a[i] = 'b';
                    else if(B && C) a[i] = 'a';
                    else if(A) a[i] = 'b';
                    else if(B) a[i] = 'c';
                    else if(C) a[i] = 'a';
                }
            }
        }
        else if(a[0] == '?') a[0] = 'a'; // 字符串长度为 1 的情况 且是 "?"

        if(ok) cout << a << endl;
        else cout << -1 << endl;
    }
    return 0;
}

B.Beautiful Numbers

// https://codeforces.com/contest/1265/problem/B
/*
    题意是要找 在一个区间 [l, r] 的数据是否有序 (从 1 开始)
        结果是判断区间长度为 1 ~ n 是否满足要求

    既然是从 1 开始 如果满足条件 区间的长度必然等于区间数组里的[位置] 最大值 - 最小值 + 1
    根据这个结论就可以解决了

    样例一:
      排序前:
        数值  4 5 1 3 2 6
        位置  1 2 3 4 5 6

      排序后:
        数值  1 2 3 4 5 6
        位置  3 5 4 1 2 6

    区间长度为 3 时
        数值 [ 1 2 3 ] 4 5 6
        位置 [ 3 5 4 ] 1 2 6
        位置最大值 - 位置最小值 + 1 = 5 - 3 + 1 = 3 等于区间长度 3
    所以区间长度为 3 时可行
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;

struct node{
    int num, pla;
}mem[200005];
int T, n;

bool cmp(node a, node b){
    return a.num < b.num;
}

int main()
{
    scanf("%d", &T);
    while(T--){
        string ans;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d", &mem[i].num);
            mem[i].pla = i; // 记录位置
        }
        sort(mem + 1, mem + 1 + n, cmp); // 把数据从 1 ~ n 升序排序

        int minn = n, maxx = 1;
        for(int i = 1; i <= n; i++){ // i 的大小等同于 区间的大小
//            printf("num:%d pla:%d\n", mem[i].num, mem[i].pla);
            // 更新当前区间里位置的最大最小值
            if(mem[i].pla < minn) minn = mem[i].pla;
            if(mem[i].pla > maxx) maxx = mem[i].pla;

            // 判断
            if(maxx - minn + 1 == i) ans += '1';
            else ans += '0';
        }

        cout << ans << endl; // 用 string 输出
    }

    return 0;
}

C.Beautiful Regional Contest

// https://codeforces.com/contest/1265/problem/C
/*
    贪心构造问题吧

    条件很多,但也很好利用
    1.获奖人数最多只有参赛人数的一半
    2.金牌的A题数 > 银牌的A题数 > 铜牌的A题数
    3.金牌的得奖数 < 银牌的, 铜牌的 (银牌与铜牌的多少没有要求)

    把 A 题最多的一组人授予金牌
    然后先依次给后面的人银牌,当银牌数比金牌数多时,剩下的都给铜牌 (这样容易避免铜牌数为 0 的情况)
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int T, n, cnt, a, x, y, z;
int mem[1000006];
int que[1000006];

bool cmp(int a, int b) { return a > b; }

int main()
{
    scanf("%d", &T);
    while(T--){
        // 初始化
        x = y = z = 0;
        for(int i = 0; i < cnt; i++){
            mem[que[i]] = 0;
        }
        cnt = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i++){
            scanf("%d", &a);
            if(mem[a] == 0){
                que[cnt++] = a; // 类似 set
            }
            mem[a]++;   // 桶排
        }

//        sort(que, que + cnt, cmp); // 因为题目就有降序输入,就不用 sort 了

        bool ok = true;

        int tot = n / 2; // 可以获奖的总人数 1
        x = mem[que[0]]; // 获得金牌的人数
        int last = tot - x; // 剩下银牌和铜牌最多的总数

        bool Z = false;
        for(int i = 1; i < cnt && last > 0; i++){
//            printf("x:%d y:%d z:%d last:%d\n", x, y, z, last);
            if(last < mem[que[i]]) break; // 当前组的人数比可给奖牌人数多时,就不能给了 (见样例 5)

            if(!Z){ // 开关 false 给银牌; true 给铜牌
                y += mem[que[i]];
                if(y > x){  // 银牌一旦符合了条件就给铜牌加
                    Z = true;
                }
            }
            else {
                z += mem[que[i]];
            }
            last -= mem[que[i]];
        }

        if(x >= y || x >= z) ok = false; // 判断是否符合条件
        if(ok) printf("%d %d %d\n", x, y, z);
        else printf("0 0 0\n");
    }
    return 0;
}

D.Beautiful Sequence

// https://codeforces.com/contest/1265/problem/D
/*
    感觉像是遍历的思维构造题 有思路就很好做的
    可以把该题想象成过山车或者山峰......
*/
#include<iostream>
#include<cstdio>
using namespace std;

int n;
int cnt[5], last[5]; // last 是记录当前还有多少 0, 1, 2, 3
int ans[100005];
bool ok;

int main()
{
    for(int i = 0; i < 4; i++) {
        scanf("%d", &cnt[i]);
        n += cnt[i]; // n 就是输出的总长度
    }

    for(int i = 0; i < 4; i++){
        if(!cnt[i]) continue;
        ans[1] = i; // 依次取 0, 1, 2, 3 为第一位开始
        ok = true;
        for(int j = 0; j < 4; j++){
            last[j] = cnt[j] - (i == j); // 初始化 last
        }

        for(int j = 2; j <= n; j++){ // 因为第一位已经放了所以从第二位开始
            int p = ans[j - 1];
            if(p - 1 >= 0 && last[p - 1]) { // 往小(低)处走
                ans[j] = p - 1; last[p - 1]--;
            }
            else if(p + 1 < 4 && last[p + 1]){ // 往大(高)处走
                ans[j] = p + 1; last[p + 1]--;
            }
            else ok = false; // 假如都不能 则当前做法不可取
        }
        if(ok){
            printf("YES\n");
            for(int i = 1; i <= n; i++){
                printf("%d%c", ans[i], i == n ? '\n' : ' ');
            }
            break;
        }
    }
    if(!ok) printf("NO\n");

    return 0;
}

Rookie record growth:

Guess you like

Origin www.cnblogs.com/Ayanowww/p/11997319.html