CF1329D 题解

CF1329D

思路

转换题意。对于 \(s_i=s_{i+1}\)\(i\),加入 \(a\)\(a\) 长为 \(m\)

发现可行的 \(s\) 上操作对应 \(a\) 上:

  • \(a\) 上删 \(a_i,a_{i+1}\),其中 \(a_i\neq a_{i+1}\)\(s\) 上删 \(s[a_i+1,a_{i+1}]\),形如 b...[bca]...a。

  • \(a\) 上删 \(a_i\),其中 \(a_i\neq a_{i+1}\)\(s\) 上删 \(a[1,a_i]\),形如 [bca]...a。

显然优先操作一,答案与 \(a\) 中出现次数最大的 \(p\) 有关,设为 \(t_p\)

  • \(t_p\times2>m\)。所有非 \(p\) 都与 \(p\) 操作一,用栈模拟,知道无法操作为止。

  • 其他情况。能配就配,\(t_p\times2>m\) 就用上面。用栈模拟,动态维护 \(t\)\(p\)

从左到右操作,可以不用线段树,记录已删除量 \(del\)。处理细节。

结束后栈不空,用操作二一个一个做。可能忽略 \(s[a_m+1,n]\),再用一次操作全部做完。

code

int n,m;
vector<pii> a;
char s[maxn];
vector<pii> ans;
int t[26],tp;
pii st[maxn];
void work(){
	scanf("%s",s+1);n=strlen(s+1);
	ans.clear();mems(t,0);a.clear();
	for(int i=1;i<n;i++)if(s[i]==s[i+1]){
		a.push_back({i,s[i]-'a'});
		t[s[i]-'a']++;
	}
	m=a.size();
	int p=0;for(int i=1;i<26;i++)if(t[p]<t[i])p=i;
	int del=0;tp=0;
	if(t[p]*2>m){
		for(pii i:a){
			if(!tp||st[tp].second==i.second||((st[tp].second!=p)*(i.second!=p)))st[++tp]={i.first-del,i.second};
			else{
				ans.push_back({st[tp].first+1,i.first-del});
				del+=i.first-del-st[tp].first-1+1;
				tp--;
			}
		}
	}else{
		for(pii i:a){
			if(!tp||st[tp].second==i.second)st[++tp]={i.first-del,i.second};
			else{
				t[st[tp].second]--;t[i.second]--;m-=2;
				int pp=p;
				p=0;for(int j=1;j<26;j++)if(t[p]<t[j])p=j;
				if(t[p]*2<=m+1){
					ans.push_back({st[tp].first+1,i.first-del});
					del+=i.first-del-st[tp].first-1+1;
					tp--;
				}
				else{
					t[st[tp].second]++;t[i.second]++;m+=2;
					p=pp;
					st[++tp]={i.first-del,i.second};
				}
			}
		}
	}
	while(tp){
		pii u=st[tp];tp--;
		if(!tp)ans.push_back({1,u.first}),del+=u.first;
		else{
			ans.push_back({st[tp].first+1,u.first});
			del+=u.first-st[tp].first-1+1;
		}
	}
	if(del!=n)ans.push_back({1,n-del});
	printf("%lld\n",(int)ans.size());
	for(pii i:ans)printf("%lld %lld\n",i.first,i.second);
}
posted @ 2024-05-10 19:52  yhddd  阅读(9)  评论(0编辑  收藏  举报