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);
}