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();
//}
}
由于昨晚放弃思考了所以代码写了巨长……
这次的题都是贪心构造。