HDU 3308 LCIS(线段树区间合并)
题意
q种操作,查询区间内最长连续上升子序列的长度,或者修改某个点的值
题解
线段树维护:区间内最长连续上升子序列的长度sub、区间内以左端点为起点的最长连续上升子序列的长度lsub、区间内以右端点为终点的最长连续上升子序列的长度rsub、区间左端点的值l和右端点的值r。
1 #define IO std::ios::sync_with_stdio(0); 2 #include <bits/stdc++.h> 3 #define iter ::iterator 4 using namespace std; 5 typedef long long ll; 6 typedef pair<ll,ll>P; 7 #define pb push_back 8 #define se second 9 #define fi first 10 #define rs o*2+1 11 #define ls o*2 12 const ll inf=0x7fffffff; 13 const int N=1e5+5; 14 struct node{ 15 int sub; 16 int lsub,rsub; 17 int l,r; 18 }a[N*4]; 19 void pu(int o,int len){ 20 a[o].l=a[ls].l; 21 a[o].r=a[rs].r; 22 a[o].sub=max(a[ls].sub,a[rs].sub); 23 if(a[rs].l>a[ls].r){ 24 a[o].sub=max(a[o].sub,a[ls].rsub+a[rs].lsub); 25 } 26 a[o].lsub=a[ls].lsub; 27 if(a[ls].lsub==len-len/2&&a[rs].l>a[ls].r){ 28 a[o].lsub+=a[rs].lsub; 29 } 30 a[o].rsub=a[rs].rsub; 31 if(a[o].rsub==len/2&&a[rs].l>a[ls].r){ 32 a[o].rsub+=a[ls].rsub; 33 } 34 } 35 void build(int o,int l,int r){ 36 if(l==r){ 37 int x; 38 scanf("%d",&x); 39 a[o].l=a[o].r=x; 40 a[o].sub=a[o].lsub=a[o].rsub=1; 41 return; 42 } 43 int m=(l+r)/2; 44 build(ls,l,m); 45 build(rs,m+1,r); 46 pu(o,r-l+1); 47 } 48 void up(int o,int l,int r,int p,int v){ 49 if(l==r&&l==p){ 50 a[o].l=a[o].r=v; 51 return; 52 } 53 int m=(l+r)/2; 54 if(p<=m)up(ls,l,m,p,v); 55 else up(rs,m+1,r,p,v); 56 pu(o,r-l+1); 57 } 58 int query(int o,int l,int r,int ql,int qr){ 59 if(l>=ql&&r<=qr){ 60 return a[o].sub; 61 } 62 int m=(l+r)/2; 63 int res=0; 64 if(ql<=m)res=max(res,query(ls,l,m,ql,qr)); 65 if(qr>m)res=max(res,query(rs,m+1,r,ql,qr)); 66 if(ql<=m&&qr>m&&a[ls].r<a[rs].l){ 67 res=max(res,min(a[ls].rsub,m-ql+1)+min(a[rs].lsub,qr-m)); 68 } 69 return res; 70 } 71 int T,n,q; 72 int main(){ 73 scanf("%d",&T); 74 while(T--){ 75 scanf("%d%d",&n,&q); 76 build(1,1,n); 77 char s[10]; 78 while(q--){ 79 int x,y; 80 scanf("%s%d%d",s,&x,&y); 81 x++; 82 if(s[0]=='U')up(1,1,n,x,y); 83 else{ 84 y++; 85 printf("%d\n",query(1,1,n,x,y)); 86 } 87 } 88 } 89 }