hdu 3397 线段树成段更新

题目不难但是很复杂,写的线段树比较繁琐。

线段树的成段更新要使用标记。首先三种操作对应三种标记: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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值