D. Linguistics (贪心+观察题目特性(数列特性))(CF 794 d2)

D. Linguistics time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard output Alina has discovered a weird language, which contains only 4 words: A, B, AB, BA. It also turned out that there are no spaces in this language: a sentence is written by just concatenating its words into a single string. Alina has found one such sentence s and she is curious: is it possible that it consists of precisely a words A, b words B, c words AB, and d words BA? In other words, determine, if it's possible to concatenate these a+b+c+d words in some order so that the resulting string is s. Each of the a+b+c+d words must be used exactly once in the concatenation, but you can choose the order in which they are concatenated. Input The first line of the input contains a single integer t (1≤t≤105) — the number of test cases. The description of the test cases follows. The first line of each test case contains four integers a, b, c, d (0≤a,b,c,d≤2⋅105) — the number of times that words A, B, AB, BA respectively must be used in the sentence. The second line contains the string s (s consists only of the characters A and B, 1≤|s|≤2⋅105, |s|=a+b+2c+2d) — the sentence. Notice that the condition |s|=a+b+2c+2d (here |s| denotes the length of the string s) is equivalent to the fact that s is as long as the concatenation of the a+b+c+d words. The sum of the lengths of s over all test cases doesn't exceed 2⋅105. Output For each test case output YES if it is possible that the sentence s consists of precisely a words A, b words B, c words AB, and d words BA, and NO otherwise. You can output each letter in any case. Example inputCopy 8 1 0 0 0 B 0 0 1 0 AB 1 1 0 1 ABAB 1 0 1 1 ABAAB 1 1 2 2 BAABBABBAA 1 1 2 3 ABABABBAABAB 2 3 5 4 AABAABBABAAABABBABBBABB 1 3 3 10 BBABABABABBBABABABABABABAABABA outputCopy NO YES YES YES YES YES NO YES Note In the first test case, the sentence s is B. Clearly, it can't consist of a single word A, so the answer is NO. In the second test case, the sentence s is AB, and it's possible that it consists of a single word AB, so the answer is YES. In the third test case, the sentence s is ABAB, and it's possible that it consists of one word A, one word B, and one word BA, as A+BA+B=ABAB. In the fourth test case, the sentence s is ABAAB, and it's possible that it consists of one word A, one word AB, and one word BA, as A+BA+AB=ABAAB. In the fifth test case, the sentence s is BAABBABBAA, and it's possible that it consists of one word A, one word B, two words AB, and two words BA, as BA+AB+B+AB+BA+A=BAABBABBAA.
思路:
- 题目已经保证a+b+c+d=|s|
- 首先判断 A,B 的个数能不能组成 A,B,AB,BA,
- 然后判断给定的序列 能不能找出 C 个AB 和 D BA
- 于是重复数列不用看, 就看相邻不同的数列
- 有 奇数,偶数个情况:
- 偶数 : ABABABAB, BABABABA, 发现如果去掉开头 和结尾, 就会分别变成对方 BABABA, ABABAB, (VAL-1)
- 奇数 ABABABABA, BABABAB, 发现 任意去某个字符, 就可以形成 a个AB+b个BA (a+b=长度/2(向下取整))
- 贪心的 让 AB的个数刚刚满足 c, 让BA的个数尽量大, 看能否符合条件不
- 当然 对于偶数,就让他们填充各自位子,然后多退少补利用 奇数+偶数, 按照上面一个步骤贪心
- 利用 偶数时 在贪心一下, 然长度长的先搞,因为每转化一次要付出 一个AB的代价,所以能用一个数列,就不用2个

#include <bits/stdc++.h> using namespace std; #define ri register int #define M 200005 // 14:50 template <class G> void read(G &x) { x=0;int f=0;char ch=getchar(); while(ch<'0'||ch>'9'){f=ch=='-';ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } int t; string s; struct dian{ int val; bool operator <(const dian t)const { return val>t.val; } }aa[M],bb[M],cc[M]; int main(){ cin>>t; while(t--) { int a,b,c,d; cin>>a>>b>>c>>d; cin>>s; int A=0,B=0; int n1=0,n2=0,n3=0; for(ri i=0;i<s.length();i++) { if(s[i]=='A') A++; else B++; } if(A!=a+d+c||B!=b+c+d) { printf("NO\n"); continue; } int tmp=0;char cur; for(ri i=0;i<s.length();i++) { if(i==0) { tmp=1;cur=s[i]; } else { if(s[i-1]!=s[i]) { tmp++;cur=s[i]; } else { if(tmp<=1) { tmp=1;cur=s[i]; continue; } if(tmp&1) { cc[++n3].val=tmp/2; } else { if(cur=='A') { bb[++n2].val=tmp/2; } if(cur=='B') { aa[++n1].val=tmp/2; } } tmp=1;cur=s[i]; } } } if(tmp>1) { if(tmp&1) { cc[++n3].val=tmp/2; } else { if(cur=='A') { bb[++n2].val=tmp/2; } if(cur=='B') { aa[++n1].val=tmp/2; } } } int tmpc=0,tmpd=0; for(ri i=1;i<=n1;i++) { tmpc+=aa[i].val; } for(ri i=1;i<=n2;i++) { tmpd+=bb[i].val; } if(tmpc<c) { for(ri i=1;i<=n3;i++) { if(tmpc+cc[i].val<c) { tmpc+=cc[i].val; cc[i].val=0; } else { cc[i].val-=(c-tmpc); tmpc=c; break; } } } if(tmpc<c&&tmpd<=d) { printf("NO\n"); continue; } if(tmpc<c) { sort(bb+1,bb+1+n2); for(ri i=1;i<=n2;i++) { if(tmpd-bb[i].val>=d) { tmpd-=bb[i].val; tmpc+=bb[i].val-1; if(tmpc>=c) break; } else { if(tmpd-d-1>=1) tmpc+=tmpd-d-1; break; } } if(tmpc<c) printf("NO\n"); else printf("YES\n"); continue; } for(ri i=1;i<=n3;i++) { tmpd+=cc[i].val; } if(tmpd<d) { sort(aa+1,aa+1+n1); for(ri i=1;i<=n1;i++) { if(tmpc-aa[i].val>=c) { tmpc-=aa[i].val; tmpd+=aa[i].val-1; if(tmpd>=d) break; } else { if(tmpc-c-1>=1) tmpd+=tmpc-c-1; break; } } if(tmpd<d) { //cout<<A<<" "<<a+d+c<<endl; printf("NO\n");continue; } } printf("YES\n"); } return 0; }
本蒟蒻写的代码也太长了吧!!一点也不简洁!!!