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

總結

這道題我一直做了很久纔想出來,通用的構造形式的推導花了很多功夫,因爲我陷入了一種困境,上面說的三個部分的相鄰元素的確認讓我難以下手寫代碼。直到我畫出了一幅圖,然後根據圖寫代碼才得出解。

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