25pts 求调(过sub2,4)
查看原帖
25pts 求调(过sub2,4)
399475
_XHY20180718_楼主2023/8/20 23:39

RT,思路就是用数组 cc 记录每个形如TBTB..BTTB..TBTB中对于每个B,如果要将其变为 T,需要变换的 BTTB 中第一个 B 出现的位置,若左右两边均有 BTTB 则赋值为 −1-1,然后暴力 O(n)O(n) 查找最长的区间。

查找过程中,对于每个 i∈[l,r]i\in[l,r] 的区间:

  • 若 cl−1+3c_{l-1}+3 比 ll 小,则说明可以向左扩展。
  • 若 cr+1c_{r+1} 比 11 大,则说明可以向右扩展。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,T,now,ans,c[N];
bool a[N],b[N];
char s[N];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>T;while(T--){
        cin>>n>>s;for(int i=0; i<=n; ++i)a[i]=b[i]=c[i]=0;
        for(int i=0; i<n-1; ++i)if(s[i]=='T'&&s[i+1]=='B')a[i]=1;
        for(int i=0; i<n-3; ++i)
            if(s[i]=='B'&&s[i+1]=='T'&&s[i+2]=='T'&&s[i+3]=='B'){
                b[i]=1;
                if(c[i])c[i]=-1;else c[i]=i+1;
                if(c[i+3])c[i+3]=-1;else c[i+3]=i+1;
            }
        for(int i=5; i<n; ++i){
            if(s[i]=='B'&&c[i-2]&&a[i-1]){
                if(c[i]&&c[i]!=c[i-2]){c[i]=-1;continue;}
                c[i]=c[i-2];
            }
        }
        for(int i=0; i<n-6; ++i)
            if(s[i]=='B'&&c[i+2]&&a[i+1]){
                if(c[i]&&c[i]!=c[i+2]){c[i]=-1;continue;}
                c[i]=c[i+2];
            }
        for(int i=n; i>=1; --i)s[i]=s[i-1],c[i]=c[i-1];
        ans=now=0;for(int l=0,r=1; r<=n; ++r){
            if(s[r]=='T'){
                int x=0;
                if(c[l]&&(c[l]+3<=l||c[l]==-1))++x;
                if(c[r+1]&&(r<c[r+1]||c[r+1]==-1))++x;
                ans=max(ans,r-l+x);
            }else l=r;
        }
        cout<<ans<<'\n';
    }return 0;
}
2023/8/20 23:39
加载中...