参考 http://dnizna.javaeye.com/blog/657622 的 写法
/**//* 题意:长度为N的01串,Q个操作 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个数
维护max1,maxL1,maxR1 最多连续1的个数,左边最多连续1的个数,右边最多连续1的个数 需要延迟标记 set rev set = 1 表示置为1 set = 0 表示置为0 set = -1 表示没有置数 rev = 1表示需要翻转
所以在需要修改时,遇到整段修改的,将该段的值更新为正确的 如set 1 的话 sum = right - left +1 然后对于其儿子的,不用更新!直接在该段标记set = 1 表示以后孩子需要更新,但该段已经是正确的值!!! 标记的做法主要就是上面说的了,某一段是正确的,但标记其儿子等都需要修改 每次遇到一条线段时,push_down() ,这样子实现了延迟更新了
如果set = 1,rev = 1这样子并不表明是先set,还是先reverse,就这里的细节了!!
但如果要set的话,必定不需再reverse了 所以在某一段,如果其需要set,更新孩子,将该标记传给孩子,表明孩子的孩子以后需要更新 同时,将孩子的rev = 0 即: rev + set -> set set + rev -> set + rev 所以push_down()那里的处理顺序是: if(set) if(rev) 两者是并列的!!
考虑例子: [0 4] [0 2] 先将[0,2]标记(set or rev),接下来是标记[0,4],上面的覆盖下面了 所以为set的话,[0,2]的rev置为0了 rev的话,就传下去 所以push_down()的if 是并列的 */ #include<cstdio> #include<cstring> #include<algorithm>
using namespace std;
const int MAXN = 100010;
int x[MAXN];
struct Node { int max0,maxL0,maxR0; int max1,maxL1,maxR1; int sum,set,rev; };
struct SegTree { Node nodes[MAXN*3];
void update(int p,int left,int right) { if(left == right)return; nodes[p].sum = nodes[2*p].sum + nodes[2*p+1].sum;
int mid = (left+right)>>1;
nodes[p].maxL0 = nodes[2*p].maxL0; if(nodes[p].maxL0 == mid-left+1)nodes[p].maxL0 += nodes[2*p+1].maxL0; nodes[p].maxR0 = nodes[2*p+1].maxR0; if(nodes[p].maxR0 == right-mid)nodes[p].maxR0 += nodes[2*p].maxR0; nodes[p].max0 = max(nodes[2*p].max0,nodes[2*p+1].max0); nodes[p].max0 = max(nodes[p].max0,nodes[2*p].maxR0+nodes[2*p+1].maxL0);
nodes[p].maxL1 = nodes[2*p].maxL1; if(nodes[p].maxL1 == mid-left+1)nodes[p].maxL1 += nodes[2*p+1].maxL1; nodes[p].maxR1 = nodes[2*p+1].maxR1; if(nodes[p].maxR1 == right-mid)nodes[p].maxR1 += nodes[2*p].maxR1; nodes[p].max1 = max(nodes[2*p].max1,nodes[2*p+1].max1); nodes[p].max1 = max(nodes[p].max1,nodes[2*p].maxR1+nodes[2*p+1].maxL1); } void push_down(int p,int left,int right) { if(left == right)return; int mid = (left+right)>>1; //set 与 rev 是并列的!!! if(nodes[p].set != -1) { int val = nodes[p].set; nodes[p].set = -1; nodes[2*p].set = nodes[2*p+1].set = val; nodes[2*p].rev = nodes[2*p+1].rev = 0;//将孩子的rev置为0 nodes[2*p].sum = val==1?mid-left+1:0; nodes[2*p].max0 = nodes[2*p].maxL0 = nodes[2*p].maxR0 = val==0?mid-left+1:0; nodes[2*p].max1 = nodes[2*p].maxL1 = nodes[2*p].maxR1 = val==1?mid-left+1:0;
nodes[2*p+1].sum = val==1?right-mid:0; nodes[2*p+1].max0 = nodes[2*p+1].maxL0 = nodes[2*p+1].maxR0 = val==0?right-mid:0; nodes[2*p+1].max1 = nodes[2*p+1].maxL1 = nodes[2*p+1].maxR1 = val==1?right-mid:0; } if(nodes[p].rev) { nodes[p].rev = false; nodes[2*p].rev ^= 1;//这里是翻转!!! nodes[2*p+1].rev ^= 1; nodes[2*p].sum = mid-left+1 - nodes[2*p].sum; swap(nodes[2*p].max0,nodes[2*p].max1); swap(nodes[2*p].maxL0,nodes[2*p].maxL1); swap(nodes[2*p].maxR0,nodes[2*p].maxR1);
nodes[2*p+1].sum = right - mid - nodes[2*p+1].sum; swap(nodes[2*p+1].max0,nodes[2*p+1].max1); swap(nodes[2*p+1].maxL0,nodes[2*p+1].maxL1); swap(nodes[2*p+1].maxR0,nodes[2*p+1].maxR1); } }
void build(int p,int left,int right) { nodes[p].set = -1; nodes[p].rev = 0; if(left == right) { nodes[p].sum = x[left]; nodes[p].max0 = nodes[p].maxL0 = nodes[p].maxR0 = (x[left]==0); nodes[p].max1 = nodes[p].maxL1 = nodes[p].maxR1 = (x[left]==1); return; } int mid = (left+right)>>1; build(2*p,left,mid); build(2*p+1,mid+1,right); update(p,left,right); }
void change(int p,int left,int right,int l,int r,int op) { push_down(p,left,right); if(l<=left && right<=r) { if(op == 2) { nodes[p].rev = true; nodes[p].sum = right - left + 1 - nodes[p].sum; swap(nodes[p].max0,nodes[p].max1); swap(nodes[p].maxL0,nodes[p].maxL1); swap(nodes[p].maxR0,nodes[p].maxR1); } else { nodes[p].set = op; nodes[p].sum = op==1?right-left+1:0; nodes[p].max0 = nodes[p].maxL0 = nodes[p].maxR0 = op==0?right-left+1:0; nodes[p].max1 = nodes[p].maxL1 = nodes[p].maxR1 = op==1?right-left+1:0; } return; } int mid = (left+right) >>1; if(l>mid)change(2*p+1,mid+1,right,l,r,op); else if(r<=mid)change(2*p,left,mid,l,r,op); else { change(2*p,left,mid,l,mid,op); change(2*p+1,mid+1,right,mid+1,r,op); } update(p,left,right); }
int query(int p,int left,int right,int l,int r,int op) { push_down(p,left,right); if(l<=left && right<=r) { if(op==3)return nodes[p].sum; return nodes[p].max1; } int mid = (left+right)>>1; if(l>mid)return query(2*p+1,mid+1,right,l,r,op); if(r<=mid)return query(2*p,left,mid,l,r,op); if(op==3)return query(2*p,left,mid,l,mid,op)+query(2*p+1,mid+1,right,mid+1,r,op); int ans = max(query(2*p,left,mid,l,mid,op),query(2*p+1,mid+1,right,mid+1,r,op)); int L = min(nodes[2*p].maxR1,mid+1-l); int R = min(nodes[2*p+1].maxL1,r-mid); ans = max(ans,L+R); return ans; } };
SegTree segTree;
int main() { #ifdef ONLINE_JUDGE #else freopen("in","r",stdin); #endif int T; for(scanf("%d",&T);T--;) { int N,Q; int q,a,b; scanf("%d%d",&N,&Q); for(int i=0;i<N;i++) scanf("%d",&x[i]); segTree.build(1,0,N-1); for(int i=0;i<Q;i++) { scanf("%d%d%d",&q,&a,&b); if(q<=2)segTree.change(1,0,N-1,a,b,q); else printf("%d\n",segTree.query(1,0,N-1,a,b,q)); } } return 0; }
|