题目不难但是很复杂,写的线段树比较繁琐。
线段树的成段更新要使用标记。首先三种操作对应三种标记:0表示没有需要处理的延迟操作,1表示需要全部赋值成1,-1表示需要全部赋值成0,2表示全部取反。在更新2时要注意一下,如果之前是1,变成-1;之前是-1变成1;之前是2变成0(wa了好久都是忘记考虑这种情况);之前是0变成2;
对于置换这个操作,我在树的节点中存了l0,r0,m0和rl1,r1,m1分别表示当前段从左,从右,以及总体的最大连续的0/1的数目,这样在置换的时候只要0与1的对应数据互换就好
自己犯了不少错误,更新的时候忘记更新标记,还有建树的时候最开始只在left==right的时候更新了标记。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
struct Tree
{
int sum;
int l1,r1,m1;
int l0,r0,m0;
int vis;
}tree[1200005];
int a[100005];
int n,m,h1,h2,h3;
int max(int a,int b)
{
if(a>b)return a;
else return b;
}
int min(int a,int b)
{
if(a<b)return a;
else return b;
}
void update(int left,int right,int root)
{
int mid;
mid=(left+right)/2;
if(tree[root].vis==1)
{
tree[root<<1].l1=tree[root<<1].m1=tree[root<<1].r1=tree[root<<1].sum=mid-left+1;
tree[root<<1].l0=tree[root<<1].r0=tree[root<<1].m0=0;
tree[root<<1].vis=1;
tree[root<<1|1].l1=tree[root<<1|1].m1=tree[root<<1|1].r1=tree[root<<1|1].sum=right-(mid+1)+1;
tree[root<<1|1].l0=tree[root<<1|1].r0=tree[root<<1|1].m0=0;
tree[root<<1|1].vis=1;
}
else if(tree[root].vis==-1)
{
tree[root<<1].l1=tree[root<<1].m1=tree[root<<1].r1=tree[root<<1].sum=0;
tree[root<<1].l0=tree[root<<1].r0=tree[root<<1].m0=mid-left+1;
tree[root<<1].vis=-1;
tree[root<<1|1].l1=tree[root<<1|1].m1=tree[root<<1|1].r1=tree[root<<1|1].sum=0;
tree[root<<1|1].l0=tree[root<<1|1].r0=tree[root<<1|1].m0=right-(mid+1)+1;
tree[root<<1|1].vis=-1;
}
else if(tree[root].vis==2)
{
tree[root<<1].sum=mid-left+1-tree[root<<1].sum;
h1=tree[root<<1].l0;
h2=tree[root<<1].r0;
h3=tree[root<<1].m0;
tree[root<<1].l0=tree[root<<1].l1;
tree[root<<1].r0=tree[root<<1].r1;
tree[root<<1].m0=tree[root<<1].m1;
tree[root<<1].l1=h1;
tree[root<<1].r1=h2;
tree[root<<1].m1=h3;
if(tree[root<<1].vis==-1)
tree[root<<1].vis=1;
else if(tree[root<<1].vis==1)
tree[root<<1].vis=-1;
else if(tree[root<<1].vis==2)
tree[root<<1].vis=0;
else
tree[root<<1].vis=2;
tree[root<<1|1].sum=right-(mid+1)+1-tree[root<<1|1].sum;
h1=tree[root<<1|1].l0;
h2=tree[root<<1|1].r0;
h3=tree[root<<1|1].m0;
tree[root<<1|1].l0=tree[root<<1|1].l1;
tree[root<<1|1].r0=tree[root<<1|1].r1;
tree[root<<1|1].m0=tree[root<<1|1].m1;
tree[root<<1|1].l1=h1;
tree[root<<1|1].r1=h2;
tree[root<<1|1].m1=h3;
if(tree[root<<1|1].vis==-1)
tree[root<<1|1].vis=1;
else if(tree[root<<1|1].vis==1)
tree[root<<1|1].vis=-1;
else if(tree[root<<1|1].vis==2)
tree[root<<1|1].vis=0;
else
tree[root<<1|1].vis=2;
}
tree[root].vis=0;
}
void build(int left,int right,int root)
{
if(left==right)
{
tree[root].l1=tree[root].m1=tree[root].r1=tree[root].sum=a[left];
if(a[left])
tree[root].l0=tree[root].m0=tree[root].r0=0;
else
tree[root].l0=tree[root].m0=tree[root].r0=1;
tree[root].vis=tree[root<<1].vis=tree[root<<1|1].vis=0;
return ;
}
int mid;
mid=(left+right)/2;
build(left,mid,root<<1);
build(mid+1,right,root<<1|1);
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
if(tree[root<<1].l1==mid-left+1)
tree[root].l1=tree[root<<1].l1+tree[root<<1|1].l1;
else
tree[root].l1=tree[root<<1].l1;
if(tree[root<<1|1].r1==right-(mid+1)+1)
tree[root].r1=tree[root<<1|1].r1+tree[root<<1].r1;
else
tree[root].r1=tree[root<<1|1].r1;
tree[root].m1=max(max(tree[root<<1].m1,tree[root<<1|1].m1),tree[root<<1].r1+tree[root<<1|1].l1);
if(tree[root<<1].l0==mid-left+1)
tree[root].l0=tree[root<<1].l0+tree[root<<1|1].l0;
else
tree[root].l0=tree[root<<1].l0;
if(tree[root<<1|1].r0==right-(mid+1)+1)
tree[root].r0=tree[root<<1|1].r0+tree[root<<1].r0;
else
tree[root].r0=tree[root<<1|1].r0;
tree[root].m0=max(max(tree[root<<1].m0,tree[root<<1|1].m0),tree[root<<1].r0+tree[root<<1|1].l0);
tree[root].vis=tree[root<<1].vis=tree[root<<1|1].vis=0;
}
void xiao(int left,int right,int root,int l,int r)
{
if(left==l && right==r)
{
tree[root].l1=tree[root].m1=tree[root].r1=tree[root].sum=0;
tree[root].l0=tree[root].m0=tree[root].r0=right-left+1;
tree[root].vis=-1;
return ;
}
int mid;
mid=(left+right)/2;
update(left,right,root);
if(r<=mid)
xiao(left,mid,root<<1,l,r);
else if(l>=mid+1)
xiao(mid+1,right,root<<1|1,l,r);
else
{
xiao(left,mid,root<<1,l,mid);
xiao(mid+1,right,root<<1|1,mid+1,r);
}
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
if(tree[root<<1].l1==mid-left+1)
tree[root].l1=tree[root<<1].l1+tree[root<<1|1].l1;
else
tree[root].l1=tree[root<<1].l1;
if(tree[root<<1|1].r1==right-(mid+1)+1)
tree[root].r1=tree[root<<1|1].r1+tree[root<<1].r1;
else
tree[root].r1=tree[root<<1|1].r1;
tree[root].m1=max(max(tree[root<<1].m1,tree[root<<1|1].m1),tree[root<<1].r1+tree[root<<1|1].l1);
if(tree[root<<1].l0==mid-left+1)
tree[root].l0=tree[root<<1].l0+tree[root<<1|1].l0;
else
tree[root].l0=tree[root<<1].l0;
if(tree[root<<1|1].r0==right-(mid+1)+1)
tree[root].r0=tree[root<<1|1].r0+tree[root<<1].r0;
else
tree[root].r0=tree[root<<1|1].r0;
tree[root].m0=max(max(tree[root<<1].m0,tree[root<<1|1].m0),tree[root<<1].r0+tree[root<<1|1].l0);
}
void man(int left,int right,int root,int l,int r)
{
if(left==l && right==r)
{
tree[root].l1=tree[root].m1=tree[root].r1=tree[root].sum=right-left+1;
tree[root].l0=tree[root].r0=tree[root].m0=0;
tree[root].vis=1;
return ;
}
int mid;
mid=(left+right)/2;
update(left,right,root);
if(r<=mid)
man(left,mid,root<<1,l,r);
else if(l>=mid+1)
man(mid+1,right,root<<1|1,l,r);
else
{
man(left,mid,root<<1,l,mid);
man(mid+1,right,root<<1|1,mid+1,r);
}
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
if(tree[root<<1].l1==mid-left+1)
tree[root].l1=tree[root<<1].l1+tree[root<<1|1].l1;
else
tree[root].l1=tree[root<<1].l1;
if(tree[root<<1|1].r1==right-(mid+1)+1)
tree[root].r1=tree[root<<1|1].r1+tree[root<<1].r1;
else
tree[root].r1=tree[root<<1|1].r1;
tree[root].m1=max(max(tree[root<<1].m1,tree[root<<1|1].m1),tree[root<<1].r1+tree[root<<1|1].l1);
if(tree[root<<1].l0==mid-left+1)
tree[root].l0=tree[root<<1].l0+tree[root<<1|1].l0;
else
tree[root].l0=tree[root<<1].l0;
if(tree[root<<1|1].r0==right-(mid+1)+1)
tree[root].r0=tree[root<<1|1].r0+tree[root<<1].r0;
else
tree[root].r0=tree[root<<1|1].r0;
tree[root].m0=max(max(tree[root<<1].m0,tree[root<<1|1].m0),tree[root<<1].r0+tree[root<<1|1].l0);
}
void zhi(int left,int right,int root,int l,int r)
{
if(left==l && right==r)
{
tree[root].sum=right-left+1-tree[root].sum;
h1=tree[root].l0;
h2=tree[root].r0;
h3=tree[root].m0;
tree[root].l0=tree[root].l1;
tree[root].r0=tree[root].r1;
tree[root].m0=tree[root].m1;
tree[root].l1=h1;
tree[root].r1=h2;
tree[root].m1=h3;
if(tree[root].vis==-1)
tree[root].vis=1;
else if(tree[root].vis==1)
tree[root].vis=-1;
else if(tree[root].vis==2)
tree[root].vis=0;
else
tree[root].vis=2;
return ;
}
int mid;
mid=(left+right)/2;
update(left,right,root);
if(r<=mid)
zhi(left,mid,root<<1,l,r);
else if(l>=mid+1)
zhi(mid+1,right,root<<1|1,l,r);
else
{
zhi(left,mid,root<<1,l,mid);
zhi(mid+1,right,root<<1|1,mid+1,r);
}
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
if(tree[root<<1].l1==mid-left+1)
tree[root].l1=tree[root<<1].l1+tree[root<<1|1].l1;
else
tree[root].l1=tree[root<<1].l1;
if(tree[root<<1|1].r1==right-(mid+1)+1)
tree[root].r1=tree[root<<1|1].r1+tree[root<<1].r1;
else
tree[root].r1=tree[root<<1|1].r1;
tree[root].m1=max(max(tree[root<<1].m1,tree[root<<1|1].m1),tree[root<<1].r1+tree[root<<1|1].l1);
if(tree[root<<1].l0==mid-left+1)
tree[root].l0=tree[root<<1].l0+tree[root<<1|1].l0;
else
tree[root].l0=tree[root<<1].l0;
if(tree[root<<1|1].r0==right-(mid+1)+1)
tree[root].r0=tree[root<<1|1].r0+tree[root<<1].r0;
else
tree[root].r0=tree[root<<1|1].r0;
tree[root].m0=max(max(tree[root<<1].m0,tree[root<<1|1].m0),tree[root<<1].r0+tree[root<<1|1].l0);
}
int he(int left,int right,int root,int l,int r)
{
if(left==l && right==r)
return tree[root].sum;
int mid;
mid=(left+right)/2;
update(left,right,root);
if(r<=mid)
return he(left,mid,root<<1,l,r);
else if(l>=mid+1)
return he(mid+1,right,root<<1|1,l,r);
else
return he(left,mid,root<<1,l,mid)+he(mid+1,right,root<<1|1,mid+1,r);
}
int lian(int left,int right,int root,int l,int r)
{
if(left==l && right==r)
return tree[root].m1;
int mid;
mid=(left+right)/2;
update(left,right,root);
if(r<=mid)
return lian(left,mid,root<<1,l,r);
else if(l>=mid+1)
return lian(mid+1,right,root<<1|1,l,r);
else
{
int ta,tb,tc;
ta=lian(left,mid,root<<1,l,mid);
tb=lian(mid+1,right,root<<1|1,mid+1,r);
tc= min(tree[root<<1].r1,mid-l+1)+min(tree[root<<1|1].l1,r-(mid+1)+1);
return max(tc,max(ta,tb));
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int i,j;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
int ta,tb,tc,ans;
while(m--)
{
scanf("%d%d%d",&tc,&ta,&tb);
ta++;tb++;
if(tc==0)
xiao(1,n,1,ta,tb);
else if(tc==1)
man(1,n,1,ta,tb);
else if(tc==2)
zhi(1,n,1,ta,tb);
else if(tc==3)
{
ans=he(1,n,1,ta,tb);
printf("%d\n",ans);
}
else
{
ans=lian(1,n,1,ta,tb);
printf("%d\n",ans);
}
}
}
return 0;
}
附个数据
3
10 20
0 0 0 0 0 0 0 0 0 0
3 1 8
0 3 8
3 5 8
2 4 4
1 1 1
3 2 8
4 5 6
1 6 7
1 5 7
1 5 9
1 3 5
0 1 1
0 6 7
1 2 4
1 4 5
4 8 8
1 8 9
0 1 8
0 1 9
3 2 2
10 20
0 0 0 0 0 0 0 0 0 0
4 0 1
3 1 1
4 0 2
0 3 8
3 3 3
3 2 4
4 7 8
0 6 8
3 1 8
3 0 2
3 0 5
4 6 6
1 2 4
3 3 4
4 1 6
3 3 5
4 7 9
0 6 8
1 0 8
1 0 4
10 20
0 0 0 0 0 0 0 0 0 0
2 6 8
4 0 6
0 4 9
2 5 9
3 2 6
1 0 4
1 3 5
0 8 9
2 1 6
0 9 9
4 3 6
2 7 7
1 2 7
3 2 6
2 4 4
4 2 6
4 4 9
1 1 7
2 6 7
3 0 9
0
0
1
0
1
0
0
0
0
0
0
0
0
0
0
0
2
3
2
0
1
2
0
5
2
3
6