hdu3308:http://acm.hdu.edu.cn/showproblem.php?pid=3308
题意:给你 100000个数列,然后更新某个点,然后查询区间内最长连续上升数列的长度,用线段树来维护区间的最大连续值,左连续最大值,右连续最大值,区间的左端点,区间的右端点。对于更新,父节点的最大值,首先求左儿子的最大值,右儿子的最大值,比较,选出大者,如果左儿子的又端点小于右儿子的左端点,则要考虑左儿子的右连续+右儿子的左连续是否大于刚才的那个值,选出大的更新。对于父节点的左连续,如果左儿子的左连续等于区间长度则父节点的左连续等于左儿子的左连续+右儿子的左连续,同理更新父节点的右连续。左端点等于左儿子的左端点,同理右端点。
对于查询:返回类型是节点类型。如果是在左儿子那里,则进入左儿子,如果在右边,则进入右儿子。如果在中间,则分别求出左边的和右边的,然后处理把这两个节点当做左儿子和右儿子进行, 对new出来的父节点进行新 。然后返回父节点。
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<iostream> 5 using namespace std; 6 struct Node{ 7 int left; 8 int right; 9 int lsum,rsum,sum; 10 int lmax,rmax; 11 }node[100003<<2]; 12 int u,v,n,m; 13 void pushup(int idx){ 14 if(node[idx<<1].rmax<node[idx<<1|1].lmax){ 15 node[idx].sum=node[idx<<1].rsum+node[idx<<1|1].lsum; 16 node[idx].sum=max(node[idx<<1].sum,max(node[idx].sum,node[idx<<1|1].sum)); 17 } 18 else 19 node[idx].sum=max(node[idx<<1].sum,node[idx<<1|1].sum); 20 if(node[idx<<1].lsum==node[idx<<1].right-node[idx<<1].left+1&&node[idx<<1].rmax<node[idx<<1|1].lmax) 21 node[idx].lsum=node[idx<<1].lsum+node[idx<<1|1].lsum; 22 else 23 node[idx].lsum=node[idx<<1].lsum; 24 if(node[idx<<1|1].rsum==node[idx<<1|1].right-node[idx<<1|1].left+1&&node[idx<<1].rmax<node[idx<<1|1].lmax) 25 node[idx].rsum=node[idx<<1].rsum+node[idx<<1|1].rsum; 26 else 27 node[idx].rsum=node[idx<<1|1].rsum; 28 node[idx].lmax=node[idx<<1].lmax; 29 node[idx].rmax=node[idx<<1|1].rmax; 30 } 31 void build(int l,int r,int idx){ 32 node[idx].left=l; 33 node[idx].right=r; 34 if(l==r){ 35 scanf("%d",&node[idx].lmax); 36 node[idx].rmax=node[idx].lmax; 37 node[idx].lsum=node[idx].rsum=node[idx].sum=1; 38 return; 39 } 40 int mid=(l+r)/2; 41 build(l,mid,idx<<1); 42 build(mid+1,r,idx<<1|1); 43 pushup(idx); 44 } 45 void update(int pos,int val,int idx){ 46 if(node[idx].left==node[idx].right){ 47 node[idx].lmax=node[idx].rmax=val; 48 return; 49 } 50 int mid=(node[idx].left+node[idx].right)/2; 51 if(mid>=pos)update(pos,val,idx<<1); 52 else 53 update(pos,val,idx<<1|1); 54 pushup(idx); 55 } 56 Node query(int s,int t,int idx){ 57 if(node[idx].left==s&&node[idx].right==t){ 58 return node[idx]; 59 } 60 int mid=(node[idx].right+node[idx].left)/2; 61 Node a,b,c; 62 if(mid>=t)return query(s,t,idx<<1); 63 else if(mid<s)return query(s,t,idx<<1|1); 64 else{ 65 a=query(s,mid,idx<<1); 66 b=query(mid+1,t,idx<<1|1); 67 if(a.rmax<b.lmax){ 68 c.sum=a.rsum+b.lsum; 69 c.sum=max(a.sum,max(c.sum,b.sum)); 70 } 71 else 72 c.sum=max(a.sum,b.sum); 73 if(a.lsum==a.right-a.left+1&&a.rmax<b.lmax) 74 c.lsum=a.lsum+b.lsum; 75 else 76 c.lsum=a.lsum; 77 if(b.rsum==b.right-b.left+1&&a.rmax<b.lmax) 78 c.rsum=a.rsum+b.rsum; 79 else 80 c.rsum=b.rsum; 81 c.lmax=a.lmax; 82 c.rmax=b.rmax; 83 return c; 84 } 85 } 86 int main(){ 87 int cas;char c; 88 scanf("%d",&cas); 89 while(cas--){ 90 scanf("%d%d",&n,&m); 91 build(1,n,1); 92 for(int i=1;i<=m;i++){ 93 cin>>c>>u>>v; 94 if(c=='Q') 95 printf("%d ",query(u+1,v+1,1).sum); 96 else 97 update(u+1,v,1); 98 } 99 } 100 } 101