HDU--3911[Black And White] 线段树

25 篇文章 0 订阅
9 篇文章 1 订阅

题意:

很简单,不多说了、、

 

思路:线段树

 

1.区间域:

s,e,len:分别表示区间的起点,终点,和区间长度

 

ll1:左边起最长的连续1个数;
rr1:右边起最长的连续1个数;
maxs1:当前区间内最长的连续1个数;

 

ll0:左边起最长的连续0个数;
rr0:右边起最长的连续0个数;
maxs0:当前区间内最长的连续0个数;

 

mark:标记当前区间的左右子区间是否已被更新
      true:表示子区间没被更新
     false:表示子区间已被更新

 

void go() //用来改变该区间的颜色(1变0;0变1)
 

2.结点更新:

(1):maxs的更新:Tnode[p].maxs1=max(Tnode[lch(p)].rr1+Tnode[rch(p)].ll1,max(Tnode[lch(p)].maxs1,Tnode[rch(p)].maxs1));

 

(2):ll的更新:
 Tnode[p].ll1=Tnode[lch(p)].ll1;
 if(Tnode[lch(p)].ll1==Tnode[lch(p)].len) Tnode[p].ll1+=Tnode[rch(p)].ll1;

 

(3):rr的更新
 Tnode[p].rr1=Tnode[rch(p)].rr1;
 if(Tnode[rch(p)].rr1==Tnode[rch(p)].len) Tnode[p].rr1+=Tnode[lch(p)].rr1;

 

结点更新函数:fuck();

void fuck(int p)//向上更新一层
{
	//更新黑色
	Tnode[p].maxs1=max(Tnode[lch(p)].rr1+Tnode[rch(p)].ll1,max(Tnode[lch(p)].maxs1,Tnode[rch(p)].maxs1));
	Tnode[p].ll1=Tnode[lch(p)].ll1;
	if(Tnode[lch(p)].ll1==Tnode[lch(p)].len) Tnode[p].ll1+=Tnode[rch(p)].ll1;
	Tnode[p].rr1=Tnode[rch(p)].rr1;
	if(Tnode[rch(p)].rr1==Tnode[rch(p)].len) Tnode[p].rr1+=Tnode[lch(p)].rr1;

	//更新白色
	Tnode[p].maxs0=max(Tnode[lch(p)].rr0+Tnode[rch(p)].ll0,max(Tnode[lch(p)].maxs0,Tnode[rch(p)].maxs0));
	Tnode[p].ll0=Tnode[lch(p)].ll0;
	if(Tnode[lch(p)].ll0==Tnode[lch(p)].len) Tnode[p].ll0+=Tnode[rch(p)].ll0;  
	Tnode[p].rr0=Tnode[rch(p)].rr0;
	if(Tnode[rch(p)].rr0==Tnode[rch(p)].len) Tnode[p].rr0+=Tnode[lch(p)].rr0;
}

 

3.注意点:

无论是Update,还是Query,在要往下一层递归前先要判断Tnode[p].mark是否等于true.若为true,则先往下更新一层。


PS.很久没做线段树的题了,今天找了一道线段树敲了一下,虽然做了将近3个小时,但是最后一次AC还是很高兴的、、、

 

CODE:

/*线段树*/
/*AC代码:687ms*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#define MAXN 100005
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lch(a) (a<<1)
#define rch(a) (a<<1|1)
using namespace std;
struct Tree
{
	int s,e,len;
	int ll1,rr1,maxs1;//黑色
	int ll0,rr0,maxs0;//白色 
	bool mark;//是否需要被更新true:需要;false:不需要
	void go()//颜色改变
	{
		int ll,rr,maxs;
		ll=ll1;ll1=ll0;ll0=ll;
		rr=rr1;rr1=rr0;rr0=rr;
		maxs=maxs1;maxs1=maxs0;maxs0=maxs;
	}
}Tnode[4*MAXN];
int N,Q;
int col[MAXN];
void fuck(int p)//向上更新一层
{
	//更新黑色
	Tnode[p].maxs1=max(Tnode[lch(p)].rr1+Tnode[rch(p)].ll1,max(Tnode[lch(p)].maxs1,Tnode[rch(p)].maxs1));
	Tnode[p].ll1=Tnode[lch(p)].ll1;
	if(Tnode[lch(p)].ll1==Tnode[lch(p)].len) Tnode[p].ll1+=Tnode[rch(p)].ll1;
	Tnode[p].rr1=Tnode[rch(p)].rr1;
	if(Tnode[rch(p)].rr1==Tnode[rch(p)].len) Tnode[p].rr1+=Tnode[lch(p)].rr1;

	//更新白色
	Tnode[p].maxs0=max(Tnode[lch(p)].rr0+Tnode[rch(p)].ll0,max(Tnode[lch(p)].maxs0,Tnode[rch(p)].maxs0));
	Tnode[p].ll0=Tnode[lch(p)].ll0;
	if(Tnode[lch(p)].ll0==Tnode[lch(p)].len) Tnode[p].ll0+=Tnode[rch(p)].ll0;  
	Tnode[p].rr0=Tnode[rch(p)].rr0;
	if(Tnode[rch(p)].rr0==Tnode[rch(p)].len) Tnode[p].rr0+=Tnode[lch(p)].rr0;
}
void Build(int p,int s,int e)
{
	Tnode[p].s=s;Tnode[p].e=e;Tnode[p].len=(e-s+1);Tnode[p].mark=false;
	if(s==e)
	{
		Tnode[p].ll1=Tnode[p].rr1=Tnode[p].maxs1=col[s];
		Tnode[p].ll0=Tnode[p].rr0=Tnode[p].maxs0=col[s]^1;
		return; 
	}
	int mid=(s+e)>>1;
	Build(lch(p),s,mid);
	Build(rch(p),mid+1,e);
	fuck(p); 
}
void Update(int p,int s,int e)
{
	if(Tnode[p].s==s&&Tnode[p].e==e)
	{
		Tnode[p].go();
		Tnode[p].mark^=1;
		return; 
	}
	int mid=(Tnode[p].s+Tnode[p].e)>>1;
	if(Tnode[p].mark)//先往下更新一层
	{
		Tnode[p].mark=false;
		Tnode[lch(p)].go();
		Tnode[rch(p)].go(); 
		Tnode[lch(p)].mark^=1;
		Tnode[rch(p)].mark^=1;
	}
	if(e<=mid) 
		Update(lch(p),s,e);
	else if(s>mid)
		Update(rch(p),s,e);
	else
	{
		Update(lch(p),s,mid);
		Update(rch(p),mid+1,e); 
	}
	fuck(p);
}
int Query(int p,int s,int e)
{
	if(Tnode[p].s==s&&Tnode[p].e==e)
	{
		return Tnode[p].maxs1;
	}
	int mid=(Tnode[p].s+Tnode[p].e)>>1;
	if(Tnode[p].mark)//往下更新
	{
		Tnode[p].mark=false;
		Tnode[lch(p)].go();
		Tnode[rch(p)].go(); 
		Tnode[lch(p)].mark^=1;
		Tnode[rch(p)].mark^=1;
		fuck(p); 
	}
	if(e<=mid)
		return Query(lch(p),s,e);
	else if(s>mid)
		return Query(rch(p),s,e);
	else
	{
		int res_l=Query(lch(p),s,mid);
		int res_r=Query(rch(p),mid+1,e);
		int ll=Tnode[lch(p)].rr1;
		int rr=Tnode[rch(p)].ll1;
		ll=min(ll,(mid-s+1));
		rr=min(rr,(e-mid));
		return max(ll+rr,max(res_l,res_r)); 
	} 
}
void Init()
{
	int i;
	for(i=1;i<=N;i++)
		scanf("%d",&col[i]);
	Build(1,1,N);//建树 
}
void Solve()
{
	int kind,s,e;
	scanf("%d",&Q);
	while(Q--)
	{
		scanf("%d%d%d",&kind,&s,&e);
		if(kind)//改变颜色
		{
			Update(1,s,e);
		}
		else
		{
			int ans=Query(1,s,e);
			printf("%d\n",ans); 
		}  
	} 
}
int main()
{
	while(scanf("%d",&N)!=EOF)
	{
		Init();
		Solve(); 
	}
return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__简言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值