UESTC 1425 Another LCIS

来源:互联网 发布:linux权限命令 编辑:程序博客网 时间:2024/05/05 16:00

也是一个求最长连续单调区间的问题,不同于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             else103             {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             else122             {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 }

 

0 0