写了好久 终于AC 还是对线段树理解不到位
0 1操作是裸区间着色 2操作是裸区间翻转(异或) 对于这两种区间操作各设两个laz变量
3操作是裸区间查询 4操作略有技巧 可以先做一下hdu3911 来弄明白4操作
这题关键是处理好着色与翻转的先后顺序关系 举个例子:
设区间 [0,4] 为 1 1 0 1 1 有两个操作 a: 0 0 4 和 b: 2 0 4
先a后b得 1 1 1 1 1 先b后a得 0 0 0 0 0 结果截然相反
思路 如果某一个区间上只有一种标记 正常pushdown即可 但如果两者都有 必须保证着色优先级更高
1 若先有着色后有翻转 则执行完着色 再执行翻转
2 若先有翻转后有着色 则放弃执行翻转 直接执行着色
但是怎么实现呢? 难道开个变量记录先后次序? 如下:
在给某区间打着色标记后移除翻转标记 打翻转标记则不用管着色标记 这样就体现了先后顺序
pushdown时也是一样操作 先看该区间有没有着色标记 有的话向下打给子区间 同时移除子区间的翻转标记
如果该区间还有翻转标记 向下打给子区间即可
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l;
int r;
int val;
int left0;
int right0;
int all0;
int left1;
int right1;
int all1;
int laz1;
int laz2;
};
node tree[400010];
int n;
void changeI(int cur,int val)
{
if(val)
{
tree[cur].val=tree[cur].r-tree[cur].l+1;
tree[cur].left0=tree[cur].right0=tree[cur].all0=0;
tree[cur].left1=tree[cur].right1=tree[cur].all1=tree[cur].r-tree[cur].l+1;
}
else
{
tree[cur].val=0;
tree[cur].left0=tree[cur].right0=tree[cur].all0=tree[cur].r-tree[cur].l+1;
tree[cur].left1=tree[cur].right1=tree[cur].all1=0;
}
return;
}
void changeII(int cur)
{
swap(tree[cur].left0,tree[cur].left1);
swap(tree[cur].right0,tree[cur].right1);
swap(tree[cur].all0,tree[cur].all1);
tree[cur].val=(tree[cur].r-tree[cur].l+1)-tree[cur].val;
return;
}
void pushup(int cur)
{
tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
tree[cur].left0=tree[2*cur].left0;
if(tree[cur].left0==tree[2*cur].r-tree[2*cur].l+1) tree[cur].left0+=tree[2*cur+1].left0;
tree[cur].right0=tree[2*cur+1].right0;
if(tree[cur].right0==tree[2*cur+1].r-tree[2*cur+1].l+1) tree[cur].right0+=tree[2*cur].right0;
tree[cur].all0=max(tree[2*cur].right0+tree[2*cur+1].left0,max(tree[2*cur].all0,tree[2*cur+1].all0));
tree[cur].left1=tree[2*cur].left1;
if(tree[cur].left1==tree[2*cur].r-tree[2*cur].l+1) tree[cur].left1+=tree[2*cur+1].left1;
tree[cur].right1=tree[2*cur+1].right1;
if(tree[cur].right1==tree[2*cur+1].r-tree[2*cur+1].l+1) tree[cur].right1+=tree[2*cur].right1;
tree[cur].all1=max(tree[2*cur].right1+tree[2*cur+1].left1,max(tree[2*cur].all1,tree[2*cur+1].all1));
return;
}
void pushdown(int cur)
{
if(tree[cur].laz1!=-1)
{
changeI(2*cur,tree[cur].laz1);
tree[2*cur].laz1=tree[cur].laz1;
tree[2*cur].laz2=0;
changeI(2*cur+1,tree[cur].laz1);
tree[2*cur+1].laz1=tree[cur].laz1;
tree[2*cur+1].laz2=0;
tree[cur].laz1=-1;
}
if(tree[cur].laz2!=0)
{
changeII(2*cur);
tree[2*cur].laz2^=1;
changeII(2*cur+1);
tree[2*cur+1].laz2^=1;
tree[cur].laz2=0;
}
return;
}
void build(int l,int r,int cur)
{
int m,t;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].laz1=-1;
tree[cur].laz2=0;
if(l==r)
{
scanf("%d",&t);
if(t)
{
tree[cur].val=1;
tree[cur].left0=tree[cur].right0=tree[cur].all0=0;
tree[cur].left1=tree[cur].right1=tree[cur].all1=1;
}
else
{
tree[cur].val=0;
tree[cur].left0=tree[cur].right0=tree[cur].all0=1;
tree[cur].left1=tree[cur].right1=tree[cur].all1=0;
}
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(cur);
return;
}
void updateI(int pl,int pr,int val,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
changeI(cur,val);
tree[cur].laz1=val;
tree[cur].laz2=0;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) updateI(pl,pr,val,2*cur);
if(pr>=tree[2*cur+1].l) updateI(pl,pr,val,2*cur+1);
pushup(cur);
return;
}
void updateII(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
changeII(cur);
tree[cur].laz2^=1;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) updateII(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) updateII(pl,pr,2*cur+1);
pushup(cur);
return;
}
int queryI(int pl,int pr,int cur)
{
int res;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
pushdown(cur);
res=0;
if(pl<=tree[2*cur].r) res+=queryI(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res+=queryI(pl,pr,2*cur+1);
return res;
}
int queryII(int pl,int pr,int cur)
{
int tl,tr,tm;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].all1;
}
pushdown(cur);
if(pr<=tree[2*cur].r) return queryII(pl,pr,2*cur);
else if(pl>=tree[2*cur+1].l) return queryII(pl,pr,2*cur+1);
else
{
tl=queryII(pl,pr,2*cur),tr=queryII(pl,pr,2*cur+1);
tm=min(tree[2*cur].r-pl+1,tree[2*cur].right1)+min(pr-tree[2*cur+1].l+1,tree[2*cur+1].left1);
return max(tm,max(tl,tr));
}
}
int main()
{
int t,q,op,l,r;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
build(0,n-1,1);
while(q--)
{
scanf("%d%d%d",&op,&l,&r);
if(op==0)
{
updateI(l,r,0,1);
}
else if(op==1)
{
updateI(l,r,1,1);
}
else if(op==2)
{
updateII(l,r,1);
}
else if(op==3)
{
printf("%d\n",queryI(l,r,1));
}
else
{
printf("%d\n",queryII(l,r,1));
}
}
}
return 0;
}