1 条题解

  • 0
    @ 2026-5-1 1:35:21

    考虑把 AB\tt AB 的序列转成极长连续段长度的序列 aa。由于每次能消掉长度为 2233 的相等连续子序列。所以我们可以删除任意一个长度 2\geq 2 的极长段。

    那么,我们把 aa 序列看成 01\tt 01 序列,分别表示 ai=1a_i=1ai2a_i\geq 2。那么一次操作相当于删掉一个 11 并且把其左右合并到一起。具体地,从 ?1?\dots?1?\dots 变为 1\dots 1\dots。能看作为把 11 左右两端消除掉。

    我们成功把问题转到了这个序列上,首先考虑如何判断是否能够完全消除。当 a=2k+1|a|=2k+1 时,如果 ak+1=0a_{k+1}=\tt 0aa 中有超过 kk 个连续的 0\tt 0 是显然无解的。否则,我们可以考虑把 ak+1a_{k+1} 左右第一个 1\tt 1,通过不断操作其中一个,就能把另一个挪到中间位上面。a|a| 为偶数时,我们显然能发现我们可以把 a|a| 劈成左右两边长度都是奇数的部分。分别判断即可。

    随便维护一下,复杂度 O(n)\mathcal O(n)

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define MP make_pair
    mt19937 rnd(time(0));
    const int MAXN=1e6+6;
    int pre[MAXN],suf[MAXN],a[MAXN],n,m;string s;
    vector<array<int,2> > ans;
    bool check(int l,int r){
    	int m=(l+r)>>1;
    	if(a[m]>1) return true;
    	int p=max(pre[m],l-1),q=min(suf[m],r+1);
    	return q-p-1<(r-l)/2;
    }
    void erase(int l,int r){
    	while(r-l>=3){
    		ans.push_back({r-1,2});
    		r-=2;
    	}
    	ans.push_back({l,r-l+1});
    }
    void solve(int l,int r){
    	int s=0;
    	int m=(l+r)>>1;
    	int p=pre[m],q=suf[m];
    	if(p!=m){
    		// do m-p operators s.t. p inthe middle
    		for(int i=1;i<q;i++) s+=a[i];
    		erase(s+1,s+a[q]);
    		for(int i=1;i<m-p;i++){
    			s-=a[q-i];
    			erase(s+1,s+a[q-i]+a[q+i]);
    		}
    		a[q-m+p]+=a[q+m-p];
    		for(int i=q+m-p+1;i<=r;i++) a[i-2*m+2*p]=a[i];
    	}
    	s=0;
    	for(int i=1;i<p;i++) s+=a[i];
    	erase(s+1,s+a[p]);
    	for(int i=1;i<=p-l;i++){
    		s-=a[p-i];
    		erase(s+1,s+a[p-i]+a[p+i]);
    	}
    }
    void output(){
    	cout<<ans.size()<<'\n';
    	for(auto i:ans) cout<<i[0]<<' '<<i[1]<<'\n';
    }
    int main(){
    	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	cin>>n>>s;s=" "+s;
    	for(int i=1;i<=n;i++){
    		m++;a[m]=1;
    		while(i<n&&s[i+1]==s[i]) a[m]++,i++;
    	}
    	for(int i=1;i<=m;i++) pre[i]=(a[i]>1?i:pre[i-1]);
    	suf[m+1]=m+1;
    	for(int i=m;i>=1;i--) suf[i]=(a[i]>1?i:suf[i+1]);
    	if(m&1){
    		if(check(1,m)) solve(1,m),output();
    		else cout<<"-1\n";
    	}else{
    		for(int i=1;i<=m;i+=2) if(check(1,i)&&check(i+1,m)){
    			solve(i+1,m);solve(1,i);output();
    			return 0;
    		}
    		cout<<"-1\n";
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    7132
    时间
    1000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者