因为是求“最长连续上升子序列”,所以区间合并和跨区间查询都需要建立在num[t[lch].r]<num[t[rch].l]的基础上
跨区间查询时注意需要保证所得到的答案区间实在查询区间之内
#include<stdio.h>
#include<string.h>
#define MAXN 100005
#define lch p<<1
#define rch p<<1|1
#define mid (t[p].l+t[p].r)>>1;
struct node
{
int l,r;
int lmx,rmx,mx;
int len;
}t[MAXN<<2];
int num[MAXN];
int min(int a,int b) {return a<b?a:b;}
int max(int a,int b) {return a>b?a:b;}
void pushup(int p)
{
t[p].mx=max(t[lch].mx,t[rch].mx);
t[p].lmx=t[lch].lmx;
t[p].rmx=t[rch].rmx;
if(num[t[lch].r]<num[t[rch].l])
{
t[p].mx=max(t[p].mx,t[lch].rmx+t[rch].lmx);
if(t[lch].lmx==t[lch].len) t[p].lmx+=t[rch].lmx;
if(t[rch].rmx==t[rch].len) t[p].rmx+=t[lch].rmx;
}
}
void construct(int l,int r,int p)
{
t[p].l=l,t[p].r=r,t[p].len=r-l+1;
if(l==r)
{
t[p].lmx=t[p].rmx=t[p].mx=1;
return ;
}
int m=mid;
construct(l,m,lch);
construct(m+1,r,rch);
pushup(p);
}
void modify(int x,int p)
{
if(t[p].l==t[p].r) return ;
int m=mid;
if(x<=m) modify(x,lch);
else modify(x,rch);
pushup(p);
}
int query(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r) return t[p].mx;
int m=mid;
if(r<=m) return query(l,r,lch);
else if(l>m) return query(l,r,rch);
else
{
int t1=query(l,m,lch),
t2=query(m+1,r,rch),
t3=0;
if(num[t[lch].r]<num[t[rch].l])
{
int llmx=min(t[lch].rmx,t[lch].r-l+1),
rrmx=min(t[rch].lmx,r-t[rch].l+1);
t3=llmx+rrmx;
}
return max(max(t1,t2),t3);
}
}
int main()
{
int cas,n,m,a,b;
char op[3];
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
construct(0,n-1,1);
while(m--)
{
scanf("%s%d%d",op,&a,&b);
if(op[0]=='Q')
printf("%d\n",query(a,b,1));
else
{
num[a]=b;
modify(a,1);
}
}
}
return 0;
}