HDU 3397 双lazy标记的问题

题目大意

对一个只有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标记的问题

时间: 2024-11-05 17:28:16

HDU 3397 双lazy标记的问题的相关文章

HDU 3397 线段树 双懒惰标记

这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1 还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻 要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了 rev操作不改变set操作,在

HDU 3911 Black And White (线段树区间合并 + lazy标记)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911 给你n个数0和1,m个操作: 0操作  输出l到r之间最长的连续1的个数 1操作  将l到r之间的0变1,1变0 区间合并的模版题,结构体中的lsum1表示从此区间最左端开始连续1的个数,rsum1表示从此区间最右端开始连续1的个数,sum1表示此区间连续1的个数最长是多少.lsum0,rsum0,sum0也是如此.每一次1的操作将区间内lazy标记与1异或一次,异或两次就说明操作抵消了.然后

HDU 1698 Just a Hook 区间更新 lazy标记

lazy标记 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <sstream> 5 #include <string> 6 #include <algorithm> 7 #include <list> 8 #include <map> 9 #include <vector> 10 #include

HDU 3397 Sequence operation(线段树)

HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变成1,1变成0 3 a b 查询[a,b]区间1的个数 4 a b 查询[a,b]区间连续1最长的长度 思路:线段树线段合并.须要两个延迟标记一个置为01,一个翻转,然后因为4操作,须要记录左边最长0.1.右边最长0.1,区间最长0.1,然后区间合并去搞就可以 代码: #include <cstdi

【线段树】HDU 3397 Sequence operation 区间合并

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,

HDU1698 just a Hook - 带有lazy标记的线段树

2017-08-30 16:44:33 writer:pprp 上午刚刚复习了一下不带有lazy标记的线段树, 下午开始学带有lazy标记的线段树 这个是我看大佬代码敲的,但是出了很多问题, 这提醒我: 1.要注意边界条件,一个边界条件的取等或者不取等,小于或者大于出错的话就直接运行不了了 2.注意输入输出,经过多次测试,果然还是用scanf比较保险,试了试用fast_io的cin结果还是TLE 所以以后不要用cin了,cin害人啊,两个混用就更加麻烦了 这个题就是区间修改,区间查询的一道题,但

[hiho 22]线段树-lazy标记的下放

题目描述 之前提到过,线段树之所以更新查询快,是因为区间更新有lazy标记使得不需要每次都操作到叶子节点. 但是如果要操作一个节点时,其父节点上的lazy标记应当被释放,否则该节点无法得到最新的正确结果. 因而lazy标记下放的策略是在需要操作某个节点的子节点时,将该节点的lazy标记全部下放.见第69行. 同时应当注意,给某个节点增加lazy标记时,不要忘了修改该节点的相关统计值.因为更新完该节点后还要马上修改其父节点的统计值.见第80行. 代码如下: #include <stdio.h>

HDU1698 Just a Hook 【线段树】+【成段更新】+【lazy标记】

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 15889    Accepted Submission(s): 7897 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing

线段树lazy标记??Hdu4902

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 335    Accepted Submission(s): 159 Problem Description There is an old country and the king fell in love with a devil. The devil al