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