题意:求最长连续上升子序列
方法:线段树区间合并,注意pushup的合并和查询时的合并
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=4*1e5+10;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
int a[maxn],msum[maxn],lsum[maxn],rsum[maxn];
int L,R,v,pos;
void pushup(int rt,int l,int r){
int m=(l+r)>>1;
int m1=r-l+1;
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
if(lsum[rt]==m1-(m1>>1)&&a[m]<a[m+1])
lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==(m1>>1)&&a[m+1]>a[m])
rsum[rt]+=rsum[rt<<1];
msum[rt]=max(msum[rt<<1],msum[rt<<1|1]);
if(a[m+1]>a[m]) msum[rt]=max(msum[rt],lsum[rt<<1|1]+rsum[rt<<1]);
}
void build(int l,int r,int rt){
if(l==r){
msum[rt]=lsum[rt]=rsum[rt]=1;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt,l,r);
}
void update(int l,int r,int rt){
if(l==r){
a[l]=v;
return ;
}
int m=(l+r)>>1;
if(pos<=m)
update(lson);
if(pos>m)
update(rson);
pushup(rt,l,r);
}
int query(int l,int r,int rt){
if(L<=l&&R>=r)
return msum[rt];
int m=(l+r)>>1;
int ans=0;
if(L<=m) //查询分为三种情况考虑
ans=max(ans,query(lson));
if(R>m)
ans=max(ans,query(rson));
if(a[m]<a[m+1])
ans=max(ans,min(m-L+1,rsum[rt<<1])+min(R-m,lsum[rt<<1|1])); //如m-L+1<0||R-m<0则会自动去掉
return ans;
}
int main(){
int t;
int n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,n,1);
char op[2];
while(m--){
scanf("%s",op);
if(op[0]=='U'){
scanf("%d%d",&pos,&v);
pos++;
update(1,n,1);
}
else{
scanf("%d%d",&L,&R);
L++;
R++;
printf("%d\n",query(1,n,1));
}
}
}
return 0;
}