码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3397 双lazy标记的问题

时间:2014-08-08 17:51:56      阅读:333      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   for   问题   cti   

题目大意

对一个只有0和1的序列,支持以下几种操作
1.将区间所有的值变成1
2.将区间所有的值变为0
3.将区间的0和1翻转(0变成1 1变成0)
4.求区间中1的个数
5.求区间连续最长的1的个数

http://vjudge.net/problem/viewProblem.action?id=14689

整整一下午。。。简直把自己修改的都要哭了

lazy标记有先后关系,如to[]覆盖后,那么rev[]翻转标记就应该重新赋为0

我们在pushdown中,是对孩子节点进行更新,那么更新的也是孩子节点的lazy标记,to[]覆盖的也是孩子节点的标记,对于还没用过的rev[cur]是不用变的,

这是它父亲传下来的,确保了正确性的

而在update函数中,每次给to[cur]进行了赋值,那么rev[cur]就要重置为0,因为我们这是对当前节点传入的标记,覆盖执行在当前节点上

PS:就是这破玩意改了我一下午的时间

void update(int cur,int x,int y,int s,int t,int op)
{
    int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    if(x>=s&&y<=t){
        if(op==0){
            lc[cur][0]=rc[cur][0]=mc[cur][0]=y-x+1;
            lc[cur][1]=rc[cur][1]=mc[cur][1]=0;
            sum[cur]=0;
            to[cur]=0,rev[cur]=0;
        }
        else if(op==1){
            lc[cur][0]=rc[cur][0]=mc[cur][0]=0;
            lc[cur][1]=rc[cur][1]=mc[cur][1]=y-x+1;
            sum[cur]=y-x+1;
            to[cur]=1,rev[cur]=0;
        }
        else if(op==2){
            swap(lc[cur][0],lc[cur][1]);
            swap(rc[cur][0],rc[cur][1]);
            swap(mc[cur][0],mc[cur][1]);
            sum[cur]=y-x+1-sum[cur];
            rev[cur]^=1;
        }
        return;
    }
    push_down(cur,x,y);
    if(mid>=s) update(L,s,t,op);
    if(mid+1<=t) update(R,s,t,op);
    push_up(cur,x,y);
}

总代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 #define L ls,x,mid
  6 #define R rs,mid+1,y
  7 #define N 100010
  8 int to[N<<2],rev[N<<2],lc[N<<2][2],rc[N<<2][2],mc[N<<2][2],sum[N<<2],X[N];
  9 void push_up(int cur,int x,int y)
 10 {
 11     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
 12     sum[cur]=sum[ls]+sum[rs];
 13     for(int i=0;i<2;i++){
 14         lc[cur][i]=lc[ls][i],rc[cur][i]=rc[rs][i];
 15         mc[cur][i]=max(mc[ls][i],mc[rs][i]);
 16         mc[cur][i]=max(mc[cur][i],rc[ls][i]+lc[rs][i]);
 17         if(lc[ls][i]==mid-x+1) lc[cur][i]=lc[ls][i]+lc[rs][i];
 18         if(rc[rs][i]==y-mid) rc[cur][i]=rc[ls][i]+rc[rs][i];
 19     }
 20 }
 21 void push_down(int cur,int x,int y)
 22 {
 23     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
 24     if(to[cur]!=-1){
 25         to[ls]=to[rs]=to[cur];
 26         rev[ls]=rev[rs]=0;
 27         lc[ls][0]=rc[ls][0]=mc[ls][0]=to[cur]?0:mid-x+1;
 28         lc[ls][1]=rc[ls][1]=mc[ls][1]=to[cur]?mid-x+1:0;
 29         lc[rs][0]=rc[rs][0]=mc[rs][0]=to[cur]?0:y-mid;
 30         lc[rs][1]=rc[rs][1]=mc[rs][1]=to[cur]?y-mid:0;
 31         sum[ls]=to[cur]*(mid-x+1);
 32         sum[rs]=to[cur]*(y-mid);
 33         to[cur]=-1;
 34     }
 35     if(rev[cur]){
 36         rev[ls]^=1,rev[rs]^=1;
 37         swap(lc[ls][0],lc[ls][1]);
 38         swap(lc[rs][0],lc[rs][1]);
 39 
 40         swap(rc[ls][0],rc[ls][1]);
 41         swap(rc[rs][0],rc[rs][1]);
 42 
 43         swap(mc[ls][0],mc[ls][1]);
 44         swap(mc[rs][0],mc[rs][1]);
 45 
 46         sum[ls]=mid-x+1-sum[ls];
 47         sum[rs]=y-mid-sum[rs];
 48 
 49         rev[cur]=0;
 50     }
 51 }
 52 void build(int cur,int x,int y)
 53 {
 54     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
 55     to[cur]=-1,rev[cur]=0;
 56     if(x==y){
 57         lc[cur][1]=rc[cur][1]=mc[cur][1]=sum[cur]=X[x];
 58         lc[cur][0]=rc[cur][0]=mc[cur][0]=X[x]^1;
 59         //printf("%d\n",mc[cur][0]);
 60         return;
 61     }
 62     build(L);
 63     build(R);
 64     push_up(cur,x,y);
 65 }
 66 void update(int cur,int x,int y,int s,int t,int op)
 67 {
 68     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
 69     if(x>=s&&y<=t){
 70         if(op==0){
 71             lc[cur][0]=rc[cur][0]=mc[cur][0]=y-x+1;
 72             lc[cur][1]=rc[cur][1]=mc[cur][1]=0;
 73             sum[cur]=0;
 74             to[cur]=0,rev[cur]=0;
 75         }
 76         else if(op==1){
 77             lc[cur][0]=rc[cur][0]=mc[cur][0]=0;
 78             lc[cur][1]=rc[cur][1]=mc[cur][1]=y-x+1;
 79             sum[cur]=y-x+1;
 80             to[cur]=1,rev[cur]=0;
 81         }
 82         else if(op==2){
 83             swap(lc[cur][0],lc[cur][1]);
 84             swap(rc[cur][0],rc[cur][1]);
 85             swap(mc[cur][0],mc[cur][1]);
 86             sum[cur]=y-x+1-sum[cur];
 87             rev[cur]^=1;
 88         }
 89         return;
 90     }
 91     push_down(cur,x,y);
 92     if(mid>=s) update(L,s,t,op);
 93     if(mid+1<=t) update(R,s,t,op);
 94     push_up(cur,x,y);
 95 }
 96 void query1(int cur,int x,int y,int s,int t,int &ans)
 97 {
 98     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
 99     if(x>=s&&y<=t){
100         ans+=sum[cur];
101         return;
102     }
103     push_down(cur,x,y);
104     if(mid>=s) query1(L,s,t,ans);
105     if(mid+1<=t) query1(R,s,t,ans);
106 }
107 int query2(int cur,int x,int y,int s,int t)
108 {
109     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
110     if(x>=s&&y<=t){
111         return mc[cur][1];
112     }
113     push_down(cur,x,y);
114     int ans=0;
115     if(mid>=s) ans=max(ans,query2(L,s,t));
116     if(mid+1<=t) ans=max(ans,query2(R,s,t));
117     return max(ans,min(mid-s+1,rc[ls][1])+min(t-mid,lc[rs][1]));
118 }
119 int main()
120 {
121     int T,n,m,op,a,b;
122     scanf("%d",&T);
123     while(T--){
124         scanf("%d%d",&n,&m);
125         for(int i=1;i<=n;i++) scanf("%d",&X[i]);
126         build(1,1,n);
127         for(int i=0;i<m;i++){
128             scanf("%d%d%d",&op,&a,&b);
129             if(op==3){
130                 int ans=0;
131                 query1(1,1,n,a+1,b+1,ans);
132                 printf("%d\n",ans);
133             }
134             else if(op==4){
135                 printf("%d\n",query2(1,1,n,a+1,b+1));
136             }
137             else update(1,1,n,a+1,b+1,op);
138         }
139     }
140     return 0;
141 }

 

HDU 3397 双lazy标记的问题,布布扣,bubuko.com

HDU 3397 双lazy标记的问题

标签:style   blog   http   color   io   for   问题   cti   

原文地址:http://www.cnblogs.com/CSU3901130321/p/3899747.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!