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

本蒟蒻写的代码也太长了吧!!一点也不简洁!!!

posted @ 2022-06-06 11:00  VxiaohuanV  阅读(66)  评论(0编辑  收藏  举报