也是一个求最长连续单调区间的问题,不同于HDU 3308LCIS的是,单点更新变成了区间成段增加,没关系同样的方法可破之。由于是成段更新,所以比更新区间小的区间是最大连续区间长度是不变的,所以更新sum[rt],lsum[rt],rsum[rt]只需要更新到这些区间,然后向上合并就行了。
但是速度还是慢了一点699ms,总觉得哪里还有改进的地方。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define lson l,m,rt<<1 5 #define rson m+1,r,rt<<1|1 6 #define N 111111 7 8 using namespace std; 9 int sum[N<<2],lsum[N<<2],rsum[N<<2],add[N<<2],A[N]; 10 int n,q; 11 12 void PushUp(int rt,int m,int mid) 13 { 14 lsum[rt]=lsum[rt<<1]; 15 rsum[rt]=rsum[rt<<1|1]; 16 int t=1; 17 if(A[mid+1]>A[mid]) 18 { 19 if(lsum[rt]==(m-(m>>1))) 20 lsum[rt]+=lsum[rt<<1|1]; 21 if(rsum[rt]==(m>>1)) 22 rsum[rt]+=rsum[rt<<1]; 23 t=rsum[rt<<1]+lsum[rt<<1|1]; 24 } 25 sum[rt]=max(t,max(sum[rt<<1],sum[rt<<1|1])); 26 } 27 28 void build(int l,int r,int rt) 29 { 30 if(l==r) 31 { 32 scanf("%d",A+l); 33 sum[rt]=lsum[rt]=rsum[rt]=1; 34 return ; 35 } 36 int m=(l+r)>>1; 37 build(lson); 38 build(rson); 39 PushUp(rt,r-l+1,m); 40 } 41 42 void update(int L,int R,int l,int r,int rt) 43 { 44 if(L<=l&&R>=r) 45 return; 46 int m=(l+r)>>1; 47 if(L<=m) 48 update(L,R,lson); 49 if(R>m) 50 update(L,R,rson); 51 PushUp(rt,r-l+1,m); 52 } 53 54 int query(int L,int R,int l,int r,int rt) 55 { 56 if(L<=l&&R>=r) 57 return sum[rt]; 58 int m=(l+r)>>1; 59 int ans=0; 60 if(R<=m) 61 ans=max(ans,query(L,R,lson)); 62 else if(L>m) 63 ans=max(ans,query(L,R,rson)); 64 else 65 { 66 ans=max(ans,query(L,R,lson)); 67 ans=max(ans,query(L,R,rson)); 68 int ll,rr; 69 if(m-L+1>=rsum[rt<<1]) 70 ll=rsum[rt<<1]; 71 else ll=m-L+1; 72 if(R-m>=lsum[rt<<1|1]) 73 rr=lsum[rt<<1|1]; 74 else rr=R-m; 75 if(A[m+1]>A[m]) 76 ans=max(ans,ll+rr); 77 } 78 return ans; 79 } 80 81 int main(void) 82 { 83 int T; 84 int a,b,v; 85 char op[3]; 86 for(int t=scanf("%d",&T); t<=T; t++) 87 { 88 memset(add,0,sizeof(add)); 89 printf("Case #%d:\n",t); 90 scanf("%d%d",&n,&q); 91 build(1,n,1); 92 while(q--) 93 { 94 scanf("%s",op); 95 if(op[0]=='a') 96 { 97 scanf("%d%d%d",&a,&b,&v); 98 for(int i=a;i<=b;i++) 99 A[i]+=v; 100 update(a,b,1,n,1); 101 } 102 else 103 { 104 scanf("%d%d",&a,&b); 105 int ans=query(a,b,1,n,1); 106 printf("%d\n",ans); 107 } 108 } 109 } 110 return 0; 111 }
方法二:看了下别人代码,发现每个区间可以用left[rt],right[rt]将区间端点值存起来,这样每次更新的时候更新端点值就可以了:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define lson l,m,rt<<1 5 #define rson m+1,r,rt<<1|1 6 #define N 111111 7 8 using namespace std; 9 int sum[N<<2],lsum[N<<2],rsum[N<<2],add[N<<2],left[N<<2],right[N<<2]; 10 int n,q; 11 12 void PushUp(int rt,int m) 13 { 14 left[rt]=left[rt<<1]; 15 right[rt]=right[rt<<1|1]; 16 lsum[rt]=lsum[rt<<1]; 17 rsum[rt]=rsum[rt<<1|1]; 18 int t=1; 19 if(left[rt<<1|1]>right[rt<<1]) 20 { 21 if(lsum[rt]==(m-(m>>1))) 22 lsum[rt]+=lsum[rt<<1|1]; 23 if(rsum[rt]==(m>>1)) 24 rsum[rt]+=rsum[rt<<1]; 25 t=rsum[rt<<1]+lsum[rt<<1|1]; 26 } 27 sum[rt]=max(t,max(sum[rt<<1],sum[rt<<1|1])); 28 } 29 void PushDown(int rt) 30 { 31 if(add[rt])//这里用来向下更新add[rt], 32 { 33 add[rt<<1]+=add[rt]; 34 add[rt<<1|1]+=add[rt]; 35 left[rt<<1]+=add[rt]; 36 right[rt<<1]+=add[rt]; 37 left[rt<<1|1]+=add[rt]; 38 right[rt<<1|1]+=add[rt]; 39 add[rt]=0; 40 } 41 42 } 43 void build(int l,int r,int rt) 44 { 45 add[rt]=0; 46 if(l==r) 47 { 48 scanf("%d",left+rt); 49 right[rt]=left[rt]; 50 sum[rt]=lsum[rt]=rsum[rt]=1; 51 return ; 52 } 53 int m=(l+r)>>1; 54 build(lson); 55 build(rson); 56 PushUp(rt,r-l+1); 57 } 58 59 void update(int L,int R,int v,int l,int r,int rt) 60 { 61 if(L<=l&&R>=r) 62 { 63 left[rt]+=v; 64 right[rt]+=v; 65 add[rt]+=v; 66 return; 67 } 68 int m=(l+r)>>1; 69 PushDown(rt); 70 if(L<=m) 71 update(L,R,v,lson); 72 if(R>m) 73 update(L,R,v,rson); 74 PushUp(rt,r-l+1); 75 } 76 77 int query(int L,int R,int l,int r,int rt) 78 { 79 if(L<=l&&R>=r) 80 return sum[rt]; 81 PushDown(rt); 82 int m=(l+r)>>1; 83 int ans=0; 84 if(R>m) 85 ans=max(ans,query(L,R,rson)); 86 if(L<=m) 87 ans=max(ans,query(L,R,lson)); 88 if(left[rt<<1|1]>right[rt<<1]&&L<=m&&R>m) 89 { 90 int ll,rr; 91 if(m-L+1>=rsum[rt<<1]) 92 ll=rsum[rt<<1]; 93 else ll=m-L+1; 94 if(R-m>=lsum[rt<<1|1]) 95 rr=lsum[rt<<1|1]; 96 else rr=R-m; 97 ans=max(ans,ll+rr); 98 } 99 return ans; 100 } 101 102 int main(void) 103 { 104 int T; 105 int a,b,v; 106 char op[3]; 107 for(int t=scanf("%d",&T); t<=T; t++) 108 { 109 memset(add,0,sizeof(add)); 110 printf("Case #%d:\n",t); 111 scanf("%d%d",&n,&q); 112 build(1,n,1); 113 while(q--) 114 { 115 scanf("%s",op); 116 if(op[0]=='a') 117 { 118 scanf("%d%d%d",&a,&b,&v); 119 update(a,b,v,1,n,1); 120 } 121 else 122 { 123 scanf("%d%d",&a,&b); 124 int ans=query(a,b,1,n,1); 125 printf("%d\n",ans); 126 } 127 } 128 } 129 return 0; 130 }