hdu 3911——Black And White

线段树

 

//  1093MS 10568K G++
#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 100005
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((t[rt].l+t[rt].r)>>1)
int n,m;
struct tree
{
	int l,r;
	int lc,rc,lval,rval;//   左起颜色 右起颜色 左起长度 右起长度 
	int w,b;          	 //  white最长 black最长 
	int cover;        	//   是否是同一种颜色 
	int lazy;			//   延迟标记 
}t[maxn<<2];
void pushup(int rt)//向上更新 
{
	t[rt].lc=t[ls].lc, t[rt].lval=t[ls].lval;
	if(t[ls].cover!=-1&&t[rs].lc==t[ls].cover)
		t[rt].lval+=t[rs].lval;
		
	t[rt].rc=t[rs].rc, t[rt].rval=t[rs].rval;
	if(t[rs].cover!=-1&&t[ls].rc==t[rs].cover)
		t[rt].rval+=t[ls].rval;
		
	if(t[ls].cover==t[rs].cover)
		t[rt].cover=t[ls].cover;
	else
		t[rt].cover=-1;
	t[rt].w=max(t[ls].w,t[rs].w);
	t[rt].b=max(t[ls].b,t[rs].b);
	if(t[ls].rc==t[rs].lc)
		if(t[ls].rc==0)
			t[rt].w=max(t[ls].rval+t[rs].lval,t[rt].w);
		else
			t[rt].b=max(t[ls].rval+t[rs].lval,t[rt].b);
}
void init(int rt)//对该节点进行反转操作 
{
	swap(t[rt].b,t[rt].w);
	t[rt].lc^=1;
	t[rt].rc^=1;
	if(t[rt].cover!=-1)
		t[rt].cover^=1;
}
void pushdown(int rt)//向下更新 
{
	if(t[rt].lazy!=0)
	{
		init(ls);
		init(rs);
		t[rt].lazy=0;
		t[ls].lazy^=1;
		t[rs].lazy^=1;
		return;
	}
}
void build(int rt,int l,int r)
{
	t[rt].l=l,t[rt].r=r;
	t[rt].lazy=0,t[rt].cover=-1;
	if(l==r)
	{
		int x;
		scanf("%d",&x);
		if(x==1)
		{
			t[rt].b=1;
			t[rt].w=0;
			t[rt].lc=t[rt].rc=1;
			t[rt].lval=t[rt].rval=1;
			t[rt].cover=1;
		}
		else
		{
			t[rt].b=0;
			t[rt].w=1;
			t[rt].lc=t[rt].rc=0;
			t[rt].lval=t[rt].rval=1;
			t[rt].cover=0;
		}
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(rt);
}
int query(int rt,int l,int r)
{
	if(l==t[rt].l&&r==t[rt].r)
		return t[rt].b;
	pushdown(rt);
	if(r<=mid)
		return query(ls,l,r);
	else if(l>mid)
			return query(rs,l,r);
		else
		{
			int ans=0;
			int lb=query(ls,l,mid);  
	        int rb=query(rs,mid+1,r);  
	        ans=max(lb,rb);  
	        if(t[ls].rc==1&&t[rs].lc==1)  
	            ans=max(ans,min(mid-l+1,t[ls].rval)+min(r-mid,t[rs].lval));  //防止超出[l,r]的范围 
    		return ans;
		}
}
void change(int rt,int l,int r)
{
	if(l==t[rt].l&&r==t[rt].r)
	{
		t[rt].lazy^=1;
		init(rt);
		return ;
	}
	pushdown(rt);
	if(r<=mid)
		change(ls,l,r);
	else if(l>mid)
			change(rs,l,r);
		else
		{
			change(ls,l,mid);
			change(rs,mid+1,r);
		}
	pushup(rt);
}
int main()
{
	while(~scanf("%d",&n))
	{
		build(1,1,n);
		int x,l,r;
		scanf("%d",&m);
		while(m--)
		{
			scanf("%d%d%d",&x,&l,&r);
			if(x==0)
			{
				int ans=query(1,l,r);
				printf("%d\n",ans);
			}
			else
				change(1,l,r);
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值