Codeforces Round #604 (Div. 2)

A. Beautiful String CF 1265 A

题目大意

当没有连续两个字母相同时,该字符串为美丽串,给定一个含a,b,c,?的字符串,要求将?替换成a,b或c,使得该串为美丽串。若无法成为美丽串输出-1

解题思路

很显然对于每个?的取值只跟它左右两个位置有关,而它一定能取到一个合法的值,只要跟左右不同即可,而如果一开始就有连续两个字母相同则输出-1.


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

bool qwq;

char s[100500];

void check(int x){
    s[x]='a';
    if (x==0){
        if (s[x+1]=='a') s[x]='b';
    }
    else{
        if (s[x-1]=='a'||s[x+1]=='a') {
                                        s[x]='b';
                                        if (s[x-1]=='b'||s[x+1]=='b') {
                                                                        s[x]='c';
                                                                        if (s[x-1]=='c'||s[x+1]=='c') qwq=false;
                                        }
        }
         
    }
}

void Input(void) {
    scanf("%s",s);
    int len=strlen(s);
    qwq=true;
    for(int i=0;i<len;++i){
        if (qwq==false) break;
        if (i!=0&&s[i]==s[i-1]) qwq=false;
        if (s[i]=='?') check(i);
    }
    if (!qwq) printf("-1\n");
    else printf("%s\n",s); 
}

void Solve(void) {}

void Output(void) {}

main(void) {
    int kase;
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    read(kase);
    for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        Input();
        Solve();
        Output();
    }
}


B. Beautiful Numbers CF 1265 B

题目大意

给定一个排列,求每一个m<=n,是否存在l,r使得区间[l,r]是1~m的一个全排列,存在则m为美丽数字。输出一个数字串,第i个数字表示m是否是美丽数字,是则1,否则0

解题思路

很显然m=1的时候我们选择1的位置,然后我们从1的位置进行拓展,很显然我们每一次贪心的向左右两个数中较小的那个数进行扩展,才有可能得到一个1~m的全排列。


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int n,l,r,pos,cnt,mi,ma;

const int N=2e5+8;

int p[N];

void Input(void) {
    read(n);
    for(int i=1;i<=n;++i) {
        read(p[i]);
        if (p[i]==1) pos=i;
    }
}

void Solve(void) {
    p[0]=p[n+1]=3e6;
    l=r=pos;
    cnt=1;
    mi=ma=1;
    putchar('1');
    while(cnt<n){
        if (l==1){
            ++r;
            ++cnt;
            ma=MAX(ma,p[r]);
        }else if (r==n){
            --l;
            ++cnt;
            ma=MAX(ma,p[l]);
        }else if (p[l-1]>p[r+1]) {
            ++r;
            ++cnt;
            ma=MAX(ma,p[r]);
        }
        else{
            --l;
            ++cnt;
            ma=MAX(ma,p[l]);
        }
        if (cnt==ma-mi+1) putchar('1'); 
        else putchar('0');
    }
    puts("");
}

void Output(void) {}

main(void) {
    int kase;
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    read(kase);
    for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        Input();
        Solve();
        Output();
    }
}


C. Beautiful Regional Contest CF 1265 C

题目大意

n个选手参加比赛,递减给出它们解决的题数,分配g个金牌s个银牌和b个铜牌,要求g<s且g<b,且\(g+s+b\leq \dfrac {n}{2}\),且获得金牌的选手的题数严格大于获得银牌选手的题数,获得银牌的选手题数严格大于获得铜牌选手的题数,获得铜牌的选手题数严格大于获得铁牌(无牌)选手的题数,问能否做到,若能,给定一个可行的分配方案,使得发牌数最大。

解题思路

题目对于g有大小限制而s和b之间没有,则我们让g尽可能小就好了,即选解题数最高的那一组选手全部发金牌,然后发银牌,直到g>s,剩下的选手全部发铜牌,直到发的牌数恰好小于\(\dfrac {n}{2}\)即可,做不到则不可行。


神奇的代码

#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int n,g,s,b,qwq,re;

const int N=4e5+8;

int num[N],cnt[N];

void Input(void) {
    qwq=0;
    num[0]=-1;
    read(n);
    for(int a,i=1;i<=n;++i) {
        read(a);
        if (num[qwq]!=a) num[++qwq]=a;
        ++cnt[qwq];
    }
    s=g=b=re=0;
}

void Solve(void) {
    g=cnt[1];
    int i=2;
    while(s<=g) s+=cnt[i++];
    while(b<=g) b+=cnt[i++];
    if (s+g+b>n/2) g=s=b=0;
    else {while(s+g+b<=n/2) b+=cnt[i++]; b-=cnt[--i];}
    printf("%d %d %d\n",g,s,b);
    for(int i=1;i<=n;++i) num[i]=cnt[i]=0;
}

void Output(void) {}

main(void) {
    int kase;
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    read(kase);
    for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        Input();
        Solve();
        Output();
    }
}


D. Beautiful Sequence CF 1265 D

题目大意

给了a个0,b个1,c个2,d个3,要求排成一个序列,使得俩俩差值为1,输出任意符合要求序列即可,没有则NO

解题思路

  • 如果有三个数是0个,则第四个数数量为1则可行,否则不可行。
  • 如果有两个数是0个,则看另外两个数的差值是否为1,是则由植树原理再判断二者的差值是否为一,是则可行,其余情况均不可行。
  • 如果有一个数是0个,则看这个数是多少,若为1或2则不可行,当为0或3时,不失一般性,假设是0的数为0个,那么我们排列1,2,3,由植树原理可知如果\(cnt=b-1+d-1+1-c\leq 2\)则可行,即1,2,1,2,1,2......,2,1, 2, 3,2,3,2......2,3,如此排列,若cnt为1则在序列最左边放一个2,若为2则在最左边和最右边各放一个2即可。
  • 如果有零个数是0个,我们考虑0,1和2,3,首先\(b\geq a\)\(c\geq d\),否则不可行。我们按照,0,1,0,1......和......2,3,2,3如此排好后,考虑1和2之间的排列,我们如此2,1,2,1.....排列,直到用光1或者2,此时如果还有剩余的,假设1还有剩余,若剩余1个,则放到最左边,否则不可行,若2还有剩余,若剩余1个,则放到最右边,否则不可行。

    神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int a,b,c,d,mi,cnt;

bool qwq;

void Input(void) {
    cnt=0;
    read(a);
    read(b);
    read(c);
    read(d);
    cnt=(a==0)+(b==0)+(c==0)+(d==0);
}

void check1(){
    int sign=0;
    if (a==0) sign=0;
    else if (b==0) sign=1;
    else if (c==0) sign=2;
    else sign=3;
    if (sign==1||sign==2){
        qwq=true;
        return;
    }
    if (sign==3){
        b-=a-1;
        b-=c-1;
        --b;
        if (b<0||b>2){
            qwq=true;
            return;
        }
        else{
            printf("YES\n");
            if (b) --b,printf("1 ");
            for(int i=1;i<=a;++i) printf("0 1 ");
            for(int i=1;i<c;++i) printf("2 1 ");
            printf("2");
            if (b) printf(" 1\n");
            else printf("\n");
            return;
        }
    }
    else{
        c-=b-1;
        c-=d-1;
        --c;
        if (c<0||c>2){
            qwq=true;
            return;
        }
        else{
            printf("YES\n");
            if (c) --c,printf("2 ");
            for(int i=1;i<=b;++i) printf("1 2 ");
            for(int i=1;i<d;++i) printf("3 2 ");
            printf("3");
            if (c) printf(" 2\n");
            else printf("\n");
            return;
        }
    }
}

void check2(){
    int s1=-1,s2=-1;
    int cnt[4];
    cnt[0]=a;
    cnt[1]=b;
    cnt[2]=c;
    cnt[3]=d;
    if (a!=0) s1=0;
    if (b!=0) if (s1==-1) s1=1;else s2=1;
    if (c!=0) if (s1==-1) s1=2;else s2=2;
    if (d!=0) if (s1==-1) s1=3;else s2=3;
    if (s2-s1>1) {
        qwq=true;
        return;
    }
    else{
        if (ABS(cnt[s2]-cnt[s1])>1){
            qwq=true;
            return;
        }
        else{
            printf("YES\n");
            if (cnt[s2]>cnt[s1]) {for(int i=1;i<=cnt[s1];++i) printf("%d %d ",s2,s1); printf("%d\n",s2);}
            else if (cnt[s2]<cnt[s1]) {for(int i=1;i<=cnt[s2];++i) printf("%d %d ",s1,s2); printf("%d\n",s1);}
            else for(int i=1;i<=cnt[s1];++i) printf("%d %d%c",s1,s2,i==cnt[s1]?'\n':' ');
            return;
        }
    }
}

void check3(){
    int si=0;
    int cnt[4];
    cnt[0]=a;
    cnt[1]=b;
    cnt[2]=c;
    cnt[3]=d;
    for(int i=0;i<4;++i) if (cnt[i]!=0) si=i;
    if (cnt[si]==1){
        printf("YES\n");
        printf("%d\n",si);
        return;
    }
    else {
        qwq=true;
        return;
    }
}
void Solve(void) {
    qwq=false;
    if (a>b&&(c!=0||d!=0)) qwq=true;
    else if (d>c&&(b!=0||a!=0)) qwq=true;
    if (!qwq){
        if (cnt==0){
        b-=a;
        c-=d;
        mi=MIN(b,c);
        b-=mi;
        c-=mi;
        if (b==1||c==1){
            printf("YES\n");
            if (b==1) {
                printf("1 ");
                for(int i=1;i<=a;++i) printf("0 1 ");
                for(int i=1;i<=mi;++i) printf("2 1 ");
                for(int i=1;i<=d;++i) printf("2 3%c",i==d?'\n':' ');
            }
            else{
                for(int i=1;i<=a;++i) printf("0 1 ");
                for(int i=1;i<=mi;++i) printf("2 1 ");
                for(int i=1;i<=d;++i) printf("2 3 "); 
                printf("2\n");
            }
        }
        else if (b==c){
                printf("YES\n");
                for(int i=1;i<=a;++i) printf("0 1 ");
                for(int i=1;i<=mi;++i) printf("2 1 ");
                for(int i=1;i<=d;++i) printf("2 3%c",i==d?'\n':' '); 
        }
        else qwq=true;
        }
        else{
            if (cnt==1) check1();
            else if (cnt==2) check2();
            else if (cnt==3) check3();
        }
    }
    if (qwq) printf("NO\n");
}

void Output(void) {}

main(void) {
    //int kase;
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    //read(kase);
    //for (int i = 1; i <= kase; i++) {
        //printf("Case #%d: ", i);
        Input();
        Solve();
        Output();
    //}
}



由于昨晚放弃思考了所以代码写了巨长……
这次的题都是贪心构造。

猜你喜欢

转载自www.cnblogs.com/Lanly/p/11995096.html