【解题方法】线段树区间合并典型题,维护区间左端点开始最大值,右端点结束最大值,以及整体最大值,还需要维护一下区间左端点和右端点的值,这样合并就方便了。

【我的这份代码还是比较快的,在本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;
}