UESTC 1425 Another LCIS

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

 

你可能感兴趣的:(CI)