只需单点修改和求区间最大连续上升序列长度。
那么,维护左的最大升长,右的最大降长,和区间最大升长。便可区间合并。因为查询的区间合并和上推区间合并动作一致,用一个node函数抽象一下就行了。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,n) for(int (i)=0;(i)<(n);i++)
#define Rep(i,n) for(int (i)=1;(i)<=(n);i++)
const int N = 111111;
int a[N];
struct node{
int pre,suf,Max,l,r;
}b[N<<2];
node push_up(node A,node B){
node te;
te.l=A.l; te.r=B.r;
te.Max = max(A.Max,B.Max);
if(a[A.r]<a[B.l]) te.Max = max(te.Max,B.pre+A.suf);
te.pre=A.pre;
if(A.pre==A.r-A.l+1 && a[A.r]<a[B.l]) te.pre+=B.pre;
te.suf=B.suf;
if(B.suf==B.r-B.l+1 && a[A.r]<a[B.l]) te.suf+=A.suf;
return te;
}
void build(int l,int r,int rt){
if(l==r){
scanf("%d",&a[l]);
b[rt].pre=b[rt].suf=1; b[rt].Max=1;
b[rt].l=b[rt].r=r;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
b[rt] = push_up(b[rt<<1],b[rt<<1|1]);
}
void update(int l,int r,int rt,int p,int v){
if(l==r){
a[l] = v;
return ;
}
int m=(l+r)>>1;
if(p<=m) update(lson,p,v);
else update(rson,p,v);
b[rt] = push_up(b[rt<<1],b[rt<<1|1]);
}
node query(int l,int r,int rt,int L,int R){
if(L<=l&&r<=R){
return b[rt];
}
int m=(l+r)>>1;
node res; int ok=0;
if(L<=m) {res=query(lson,L,R); ok = 1;}
if(R>m){
if(ok) res=push_up(res,query(rson,L,R));
else res=query(rson,L,R);
}
return res;
}
int n,m;
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
build(1,n,1);
while(m--){
char cmd[3];
int x,y;
scanf("%s %d %d",cmd,&x,&y);
if(cmd[0]=='U'){
update(1,n,1,x+1,y);
}
else {
x++; y++;
node res = query(1,n,1,x,y);
printf("%d\n",res.Max);
}
}
}
return 0;
}