1 10 10 7 7 3 3 5 9 9 8 1 8 Q 6 6 U 3 4 Q 0 1 Q 0 5 Q 4 7 Q 3 5 Q 0 2 Q 4 6 U 6 10 Q 0 9
1 1 4 2 3 1 2 5
—————————————————————分割线——————————————————————
题目大意:
给定一个序列,有两种操作
1:U a b 将第a个元素的值改为b(下标从0开始)
2:Q a b 查询区间[a,b]的最长连续递增子序列的长度
思路:
维护某个节点区间的 左连续递增区间长度,右连续递增区间长度,总的连续递增区间长度
然后简单的查询 左、中、右 具有相同的优先级
因为修改为单点修改,因此要更新到叶子节点,push_up
虽然自己知道思路,打来打去小细节害死人啊
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100001; using namespace std; int lc[maxn<<2],rc[maxn<<2],mc[maxn<<2]; int lnum[maxn<<2],rnum[maxn<<2]; void push_up(int rt,int m) { lnum[rt]=lnum[rt<<1]; rnum[rt]=rnum[rt<<1|1]; lc[rt]=lc[rt<<1]; rc[rt]=rc[rt<<1|1]; mc[rt]=max(mc[rt<<1],mc[rt<<1|1]); if(rnum[rt<<1]<lnum[rt<<1|1]){ if(lc[rt]==(m-(m>>1))) lc[rt]+=lc[rt<<1|1]; if(rc[rt]==(m>>1)) rc[rt]+=rc[rt<<1]; mc[rt]=max(lc[rt<<1|1]+rc[rt<<1],mc[rt]); } } void build(int l,int r,int rt) { if(l==r){ scanf("%d",&lnum[rt]); rnum[rt]=lnum[rt]; mc[rt]=lc[rt]=rc[rt]=1; return ; } int m=(l+r)>>1; build(lson); build(rson); push_up(rt,r-l+1); } void update(int p,int modify,int l,int r,int rt) { if(l==r){ lnum[rt]=rnum[rt]=modify; return ; } int m=(l+r)>>1; if(p<=m) update(p,modify,lson); else update(p,modify,rson); push_up(rt,r-l+1); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R){ return mc[rt]; } int m=(l+r)>>1; int maxx=0; if(L<=m) maxx=max(maxx,query(L,R,lson)); if(m<R) maxx=max(maxx,query(L,R,rson)); if(rnum[rt<<1]<lnum[rt<<1|1]) maxx=max(maxx,min(m-L+1,rc[rt<<1])+min(R-m,lc[rt<<1|1])); return maxx; } int main() { int T,n,m; cin>>T; while(T--){ scanf("%d %d",&n,&m); build(0,n-1,1); char op[2];int a,b; while(m--){ scanf("%s %d %d",op,&a,&b); if(op[0]=='U') update(a,b,0,n-1,1); else printf("%d\n",query(a,b,0,n-1,1)); } } return 0; }