【解题方法】线段树区间合并典型题,维护区间左端点开始最大值,右端点结束最大值,以及整体最大值,还需要维护一下区间左端点和右端点的值,这样合并就方便了。
【我的这份代码还是比较快的,在本oj跑到了第一名】
【AC 代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100005;
struct node{
int l,r,len;
int lsum,rsum,msum;
int lv,rv,v;
}Tree[maxn<<2];
char s[maxn];
int a[maxn];
void pushup(int rt)
{
Tree[rt].lv = Tree[rt*2].lv;
Tree[rt].rv = Tree[rt*2+1].rv;
Tree[rt].lsum = Tree[rt*2].lsum;
Tree[rt].rsum = Tree[rt*2+1].rsum;
if(Tree[rt*2].lsum==Tree[rt*2].len && Tree[rt*2].rv<=Tree[rt*2+1].lv) Tree[rt].lsum = Tree[rt*2].lsum+Tree[rt*2+1].lsum;
if(Tree[rt*2+1].rsum==Tree[rt*2+1].len && Tree[rt*2].rv<=Tree[rt*2+1].lv) Tree[rt].rsum = Tree[rt*2].rsum+Tree[rt*2+1].rsum;
Tree[rt].msum = max(Tree[rt*2].msum,Tree[rt*2+1].msum);
if(Tree[rt*2].rv<=Tree[rt*2+1].lv) Tree[rt].msum = max(Tree[rt].msum,Tree[rt*2].rsum+Tree[rt*2+1].lsum);
}
void pushdown(int rt)
{
if(Tree[rt].v)
{
Tree[rt*2].lsum=Tree[rt*2].rsum=Tree[rt*2].msum=Tree[rt*2].len;
Tree[rt*2+1].lsum=Tree[rt*2+1].rsum=Tree[rt*2+1].msum=Tree[rt*2+1].len;
Tree[rt*2].v=Tree[rt*2+1].v=Tree[rt].v;
Tree[rt*2].lv=Tree[rt*2+1].lv=Tree[rt].v;
Tree[rt*2].rv=Tree[rt*2+1].rv=Tree[rt].v;
Tree[rt].v = 0;
}
}
void Build(int l,int r,int rt)
{
Tree[rt].l = l,Tree[rt].r = r;
Tree[rt].len = r-l+1;
Tree[rt].v = 0;
if(l==r)
{
Tree[rt].lsum=Tree[rt].rsum=Tree[rt].msum=1;
Tree[rt].lv=Tree[rt].rv=a[l];
return ;
}
int mid = (l+r)/2;
Build(l,mid,rt*2);
Build(mid+1,r,rt*2+1);
pushup(rt);
}
void update(int L,int R,int v,int rt)
{
if(L==Tree[rt].l&&Tree[rt].r==R)
{
Tree[rt].lv=Tree[rt].rv=Tree[rt].v=v;
Tree[rt].lsum=Tree[rt].rsum=Tree[rt].msum=Tree[rt].len;
return ;
}
pushdown(rt);
int mid=(Tree[rt].l+Tree[rt].r)/2;
if(R<=mid) update(L,R,v,rt*2);
else if(L>mid) update(L,R,v,rt*2+1);
else{
update(L,mid,v,rt*2);
update(mid+1,R,v,rt*2+1);
}
pushup(rt);
}
int queryans(int L,int R,int rt)
{
if(L==Tree[rt].l&&Tree[rt].r==R)
{
return Tree[rt].msum;
}
pushdown(rt);
int mid = (Tree[rt].l+Tree[rt].r)/2;
if(R<=mid) return queryans(L,R,rt*2);
else if(L>mid) return queryans(L,R,rt*2+1);
else{
int ret = max(queryans(L,mid,rt*2),queryans(mid+1,R,rt*2+1));
if(Tree[rt*2].rv<=Tree[rt*2+1].lv){
ret = max(ret,min(Tree[rt*2].rsum,mid-L+1)+min(Tree[rt*2+1].lsum,R-mid));
}
return ret;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
int n = strlen(s+1);
for(int i=1 ;i<=n; i++) a[i] = s[i]-'a'+1;
Build(1,n,1);
int q;
scanf("%d",&q);
char op1[3],op2[3];
int l,r;
while(q--)
{
scanf("%s%d%d",op1,&l,&r);
if(l>r) swap(l,r);
if(op1[0]=='Q'){
printf("%d\n",queryans(l,r,1));
}
else{
scanf("%s",op2);
update(l,r,op2[0]-'a'+1,1);
}
}
}
return 0;
}