D. Beautiful Sequence for Round 604 Div2 in Codeforces

题意

原题传送门

题目要求你将a个0,b个1,c个2和d个3排列成一个序列,使得相邻元素的差为1。其中0<=a+b+c+d<=1e5

题意分析

从数据量分析我们能够否定掉暴力的方法。必须观察题设条件总结出规律,然后根据规律设计一种guide,根据这个guide走可以判断是否能够构造出符合要求的序列。经过分析。我将整体情况分解为两种情况:

  1. abcd四个数中只有相邻的两个数大于0,另外两个数均为零。如:a=2,b=2,c=d=0;这种情况只需要判断|a-b|<=1,满足便能构造出符合要求的序列。不满足则不能构造出符合要求的序列。
  2. otherwise,其他情况只需要判断 |(b-a) - (c-d)| <= 1,如果满足便能构造出符合要求的序列,不满足则不能。

第一种情况很容易想到,也容易分析,这里直接分析第二种情况。我想出的一种通用构造情况:

(1) 0 1 ... 0 1 2 1 ... 2 1 2 3 ... 2 3  (2)

 上面的构造情况将整个结果序列分为3个部分,分别是0 1 重复部分、2 1 重复部分、2 3 重复部分。然后首位括号部分分别是多出的1 和 2可以放到首尾,并且1和2不会同时多出,因为如果同时多出则可以在中间构成一个 2 1的重复。通过这种通用方式构造出来的序列是满足要求的。

参考代码

/*
	problem:
	author: zxz
	time:
	memory:
	disadvantage:
*/


#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <math.h>
#include <queue>
#include <string>
#include <sstream>
#include <vector>
#include <string.h>
#include <time.h>

#ifndef ONLINE_JUDGE
#include <fstream>
#endif

using namespace std;

const int maxn = 2e5 + 5;
const int INF = 1e9;

void put(char c) {
    putchar(c);
    putchar(' ');
}

void put(int a, int b, char c, char d) {
    puts("YES");
    if(a >= b) {
        while(b && a) {
            printf("%c %c ", c,d);
            a--;
            b--;
        }
        if(a>b)
            printf("%c", c);
    } else {
        while(a && b) {
            printf("%c %c ",d,c);
            a--;
            b--;
        }
        if(b > a)
            printf("%c", d);
    }
    puts("");
}


void solve() {
    int a, b,c,d;
    scanf("%d %d %d %d", &a, &b,&c,&d);

    if(c == 0 && d == 0 && abs(a - b) <= 1) {
        put(a,b,'0','1');
        return ;
    }

    if(a == 0 && d == 0 && abs(b - c) <= 1) {
        put(b,c,'1','2');
        return ;
    }

    if(a == 0 && b == 0 && abs(c - d) <= 1) {
        put(c,d,'2','3');
        return ;
    }

    int ba = b -a;
    int cd = c-d;

    if(ba>= 0 && cd >= 0 && abs(ba - cd) <= 1) {
        puts("YES");
        if(ba > cd){
            printf("1 ");
        }
        while(a--){
            printf("0 1 ");
        }
        for(int i = 0; i < min(ba,cd); i++){
            printf("2 1 ");
        }
        while(d--){
            printf("2 3 ");
        }

        if(cd > ba){
            printf("2");
        }
        printf("\n");
    } else {
        puts("NO");
    }

}

int main() {
    int t = 1;
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int mao = clock();
    scanf("%d", &t);
#endif
    while(t--) {
        solve();
    }
#ifndef ONLINE_JUDGE
    cerr << "Time:" << clock() - mao << "ms" << endl;
    ifstream ansf, resf;
    ansf.open("ans.txt");
    resf.open("out.txt");
    string compare1,compare2;
    while(!ansf.eof() || !resf.eof()) {
        ansf >> compare1;
        resf >> compare2;
        if(((int)ansf.eof() ^ (int)resf.eof()) || compare1 != compare2) {
            cerr << "Result is NO" <<endl;
            return 0;
        }
    }
    cerr << "Result is YES" <<endl;
#endif
    return 0;
}

总结

这道题我一直做了很久才想出来,通用的构造形式的推导花了很多功夫,因为我陷入了一种困境,上面说的三个部分的相邻元素的确认让我难以下手写代码。直到我画出了一幅图,然后根据图写代码才得出解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章