1. 程式人生 > 其它 >D. Linguistics (貪心+觀察題目特性(數列特性))(CF 794 d2)

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≤2105) — 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|≤2105, |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.
View problem

思路:

  • 題目已經保證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

本蒟蒻寫的程式碼也太長了吧!!一點也不簡潔!!!