D. Linguistics (貪心+觀察題目特性(數列特性))(CF 794 d2)
阿新 • • 發佈:2022-06-06
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 stringView problem. 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 inthe 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; }View Code
本蒟蒻寫的程式碼也太長了吧!!一點也不簡潔!!!