【洛谷题解】AT_abc415_f 题解
怎么说呢。它的这个思路并不是很难,然后吧,个人感觉这个代码的细节并不是很多。
我是比赛一结束就会了,然后立刻补的。没怎么调,一下子就过了。
就是说,这东西是个很显然的线段树。它处理的是单点修改区间查询。
那线段树要维护啥呢?其实也很显然。或者说,比较典。
首先是这个区间的这个 \(\max\) 的长度,对吧,就记作 \(mx\) 好了。
然后呢,区间合并,也就是 push_up 的时候,还需要用到每个区间左边一段同样字母的情况,以及右边一段同样字母的情况。
左边一段字母是 \(Lh\),长度为 \(Lc\),右边的话字母 \(Rh\) 长度 \(Rc\)。
那就没事了,去维护就成。
这还是没啥难度的吧。
代码……不算很长,然后感觉细节也不多,大家看着来吧。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2e6+5;
struct Tree{
int Lc;char Lh;
int Rc;char Rh;
int mx,len;
}t[N];
int n,Q;
string s;
int ls(int u){return (u<<1);}
int rs(int u){return (u<<1|1);}
Tree operator + (const Tree x,const Tree y){
Tree A;
A.mx=max(x.mx,y.mx);
A.len=x.len+y.len;
if(x.Rh==y.Lh)A.mx=max(A.mx,x.Rc+y.Lc);
A.Lc=x.Lc,A.Lh=x.Lh;
if(x.len==x.Lc&&y.Lh==x.Lh)A.Lc+=y.Lc;
A.Rc=y.Rc,A.Rh=y.Rh;
if(y.len==y.Rc&&y.Rh==x.Rh)A.Rc+=x.Rc;
return A;
}
void build(int u,int l,int r){
if(l==r){t[u]={1,s[l],1,s[r],1,1};return;}
int mid=(l+r)/2;
build(ls(u),l,mid);build(rs(u),mid+1,r);
t[u]=t[ls(u)]+t[rs(u)];return;
}
void change(int u,int l,int r,int LR,char k){
if(l>LR||r<LR)return;
if(l==LR&&r==LR){s[l]=k;t[u]={1,k,1,k,1,1};return;}
int mid=(l+r)/2;
change(ls(u),l,mid,LR,k);change(rs(u),mid+1,r,LR,k);
t[u]=t[ls(u)]+t[rs(u)];
return;
}
Tree query(int u,int l,int r,int L,int R){
if(L<=l&&r<=R)return t[u];int mid=(l+r)/2;
if(R<=mid)return query(ls(u),l,mid,L,R);
if(L>mid)return query(rs(u),mid+1,r,L,R);
return query(ls(u),l,mid,L,R)+query(rs(u),mid+1,r,L,R);
}
int main(){
cin>>n>>Q>>s;s=" "+s;build(1,1,n);
while(Q--){
int opt;cin>>opt;
if(opt==1){int i;char x;cin>>i>>x;change(1,1,n,i,x);}
else{int l,r;cin>>l>>r;cout<<query(1,1,n,l,r).mx<<"\n";}
}
return 0;
}

浙公网安备 33010602011771号