AC 28 个点,具体可见这里。
思路是维护每个块的单块答案,向左/向右能延伸到的最远距离,具体见代码,疑似 query() 出锅。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int q,n,t,a[N];
int L[N],R[N],pos[N];
int mx[N],lft[N],rgt[N];
inline void Init(int n)
{
t=sqrt(n);
for(int i=1;i<=t;++i)
L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[t]=n;
for(int i=1;i<=t;++i)
{
int sum=1;
for(int j=L[i];j<=R[i];++j)
{
if(j>L[i]&&a[j]==a[j-1])sum++;
else sum=1;
mx[i]=max(mx[i],sum);
pos[j]=i;
}
for(int j=L[i];j<=R[i];++j)
if(a[j]==a[L[i]])lft[i]=j;
else break;
for(int j=R[i];j>=L[i];--j)
if(a[j]==a[R[i]])rgt[i]=j;
else break;
}
}
inline void Update(int x,int y)
{
int p=pos[x],sum=1;
a[x]=y;mx[p]=1;
for(int i=L[p];i<=R[p];++i)
{
if(i>L[p]&&a[i]==a[i-1])sum++;
else sum=1;
mx[p]=max(mx[p],sum);
}
for(int j=L[p];j<=R[p];++j)
if(a[j]==a[L[p]])lft[p]=j;
else break;
for(int j=R[p];j>=L[p];--j)
if(a[j]==a[R[p]])rgt[p]=j;
else break;
}
inline int Query(int l,int r)
{
int pl=pos[l],pr=pos[r];
if(pl==pr)
{
int sum=1,maxx=1;
for(int i=l;i<=r;++i)
{
if(i>l&&a[i]==a[i-1])sum++;
else sum=1;
maxx=max(maxx,sum);
}
return maxx;
}
int sum=1,maxx=1;
for(int i=l;i<=R[pl];++i)
{
if(i>l&&a[i]==a[i-1])sum++;
else sum=1;
maxx=max(maxx,sum);
}
sum=1;
for(int i=L[pr];i<=r;++i)
{
if(i>L[pr]&&a[i]==a[i-1])sum++;
else sum=1;
maxx=max(maxx,sum);
}
sum=R[pl]-max(rgt[pl],l)+1;
for(int i=pl+1;i<=pr;++i)
{
if(i!=pr)maxx=max(maxx,mx[i]);
maxx=max(sum,maxx);
if(a[L[i]]==a[R[i-1]])
{
sum+=min(lft[i],r)-L[i]+1;
maxx=max(maxx,sum);
if(lft[i]==R[i])continue;
}
sum=R[i]-rgt[i]+1;
maxx=max(sum,maxx);
}
return maxx;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
string s;
cin>>n>>q>>s;
for(int i=0;i<n;++i)a[i+1]=s[i]-'a'+1;
Init(n);
while(q--)
{
int opt,x;
cin>>opt>>x;
if(opt==1)
{
char y;cin>>y;
Update(x,y-'a'+1);
}
else
{
int y;cin>>y;
cout<<Query(x,y)<<'\n';
}
}
return 0;
}