只需单点修改和求区间最大连续上升序列长度。
那么,维护左的最大升长,右的最大降长,和区间最大升长。便可区间合并。因为查询的区间合并和上推区间合并动作一致,用一个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; }