1 条题解

  • 0
    @ 2026-5-6 9:38:30

    这个你考虑枚举所有 ii 作为左端点,怎么求最右边的右端点。令 preipre_i 为前缀和,sufisuf_i 为后缀和。

    首先可以二分右端点,只要这个区间内所有 prel1preipre_{l-1} \leq pre_i 就可以,显然这个具有单调性。

    现在左边的限制满足了,考虑右边的限制,即满足 sufr+1sufisuf_{r+1} \leq suf_i。找到 sufisuf_i 在当前区间内的最小值位置 pp,若有多个则取最右的。当 pip \leq i,那么一定有 sufp<sufr+1suf_p < suf_{r+1}。反之,令 r=p1r = p-1 则一定满足条件。

    这个随便写个 RMQ 就行了。以防空间爆炸,我前缀部分写的 ST 表,后面写的 sgt。

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    //#define int long long
    int T,n,m;
    int pre[1001000],suf[1001000];
    int st[23][1001000];
    int lg[1001000];
    int qry(int l,int r){
    	return min(st[lg[r-l+1]][l],st[lg[r-l+1]][r-(1<<lg[r-l+1])+1]);
    }
    int dat[4001000],pos[4001000];
    void pushup(int p){
    	dat[p]=min(dat[p<<1],dat[p<<1|1]);
    	if(dat[p<<1]<dat[p<<1|1]) pos[p]=pos[p<<1];
    	else pos[p]=pos[p<<1|1];
    }
    void build(int p,int L,int R){
    	if(L==R){
    		dat[p]=suf[L];pos[p]=L;
    		return;
    	}
    	int mid=L+R>>1;
    	build(p<<1,L,mid),build(p<<1|1,mid+1,R);
    	pushup(p);
    }
    pair<int,int> qry(int p,int L,int R,int l,int r){
    	if(L>r||R<l) return {0,1e18};
    	if(L>=l&&R<=r) return {pos[p],dat[p]};
    	int mid=L+R>>1;
    	pair<int,int> rl=qry(p<<1,L,mid,l,r),rr=qry(p<<1|1,mid+1,R,l,r);
    	if(rl.second<rr.second) return rl;
    	return rr;
    }
    signed main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		char c;
    		cin>>c;
    		pre[i]=pre[i-1]+(c=='0'?-1:1);
    		st[0][i]=pre[i];
    	}
    	for(int i=n;i>=1;i--){
    		suf[i]=suf[i+1]+pre[i]-pre[i-1];
    	}
    	build(1,1,n);
    	for(int i=2;i<=n;i++){
    		lg[i]=lg[i/2]+1;
    	}
    	for(int j=1;j<=22;j++){
    		for(int i=1;i<=n-(1<<j)+1;i++){
    			st[j][i]=min(st[j-1][i],st[j-1][i+(1<<j-1)]);
    		}
    	}
    	int ans=0;
    	for(int i=1;i<=n;i++){
    		if(pre[i]-pre[i-1]==1){
    			int l=i,r=n;
    			while(l<r){
    				int mid=(l+r+1)>>1;
    				if(qry(i,mid)<pre[i-1]) r=mid-1;
    				else l=mid;
    			}
    			pair<int,int> t=qry(1,1,n,i,l);
    			if(t.second<suf[l+1]) l=t.first-1;
    			ans=max(ans,l-i+1);
    		}
    	}
    	cout<<ans<<'\n';
    	return 0;
    }
    
    • 1

    信息

    ID
    708
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    9
    已通过
    2
    上传者