HDU——3911 Black And White

 

http://acm.hdu.edu.cn/showproblem.php?pid=3911

 

简单线段树变形,居然卡了我这么长时间,各种悲剧~

 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100010
#define MID(x,y) ((x+y)>>1)
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a>b?b:a)
#define swap(a,b) (a^=b,b^=a,a^=b)
struct node{
	
	int l,r;
	int sum;			//黑子连续和
	int w_sum;			//白子连续和
	int l_sum,r_sum;	//左黑连续长度, 右黑连续长度
	int wl_sum,wr_sum;	//左白连续长度, 右白连续长度
	int flag;			//标记
	
}seg_tree[N<<2];
int s[N],ans;

void Swap(int t){
	
	swap(seg_tree[t].l_sum,seg_tree[t].wl_sum);
	swap(seg_tree[t].r_sum,seg_tree[t].wr_sum);
	swap(seg_tree[t].sum,seg_tree[t].w_sum);
	
}
void updata(int t){
	
	//黑子
	seg_tree[t].sum = Max(seg_tree[L(t)].r_sum + seg_tree[R(t)].l_sum ,Max(seg_tree[L(t)].sum,seg_tree[R(t)].sum));
	seg_tree[t].l_sum = seg_tree[L(t)].l_sum;
	if(seg_tree[L(t)].l_sum == seg_tree[L(t)].r-seg_tree[L(t)].l)
		seg_tree[t].l_sum += seg_tree[R(t)].l_sum;
	seg_tree[t].r_sum = seg_tree[R(t)].r_sum;	
	if(seg_tree[R(t)].r_sum == seg_tree[R(t)].r-seg_tree[R(t)].l)
		seg_tree[t].r_sum += seg_tree[L(t)].r_sum;
	
	//白子
	seg_tree[t].w_sum = Max(seg_tree[L(t)].wr_sum + seg_tree[R(t)].wl_sum ,Max(seg_tree[L(t)].w_sum,seg_tree[R(t)].w_sum));
	seg_tree[t].wl_sum = seg_tree[L(t)].wl_sum;
	if(seg_tree[L(t)].wl_sum == seg_tree[L(t)].r-seg_tree[L(t)].l)
		seg_tree[t].wl_sum += seg_tree[R(t)].wl_sum;
	seg_tree[t].wr_sum = seg_tree[R(t)].wr_sum;
	if(seg_tree[R(t)].wr_sum == seg_tree[R(t)].r-seg_tree[R(t)].l)
		seg_tree[t].wr_sum += seg_tree[L(t)].wr_sum;
	
}
void build(int t,int l,int r)
{
	int mid = MID(l,r);
	seg_tree[t].l = l;
	seg_tree[t].r = r;
	if(r-l == 1){
		if(s[l] == 0){
			seg_tree[t].sum=0;
			seg_tree[t].l_sum=0;
			seg_tree[t].r_sum=0;
			
			seg_tree[t].w_sum=1;
			seg_tree[t].wl_sum=1;
			seg_tree[t].wr_sum=1;
			
		}
		else {
			seg_tree[t].sum=1;
			seg_tree[t].l_sum=1;
			seg_tree[t].r_sum=1;
			
			seg_tree[t].w_sum=0;
			seg_tree[t].wl_sum=0;
			seg_tree[t].wr_sum=0;
		}
		return ;
	}
	build(L(t),l,mid);
	build(R(t),mid,r);
	updata(t);
}
void insert(int t, int l, int r){
	
	//printf("<t-%d,%d,%d>\n",t,seg_tree[t].l,seg_tree[t].r);
	//printf("<l-%d   r-%d>\n",l,r);
	
	int mid = MID(seg_tree[t].l,seg_tree[t].r);
	
	if(l == seg_tree[t].l && seg_tree[t].r == r){
		Swap(t);
		seg_tree[t].flag ^=1;
		return ;
	}
	if(seg_tree[t].flag == 1){
		seg_tree[t].flag = 0;
		Swap(L(t));
		seg_tree[L(t)].flag ^=1;
		Swap(R(t));
		seg_tree[R(t)].flag ^=1;
	}
	if(mid >= r)
		insert(L(t),l,r);
	
	else if( mid <= l ) insert(R(t),l,r);
	else {
		
		insert(L(t),l,mid);
		
		insert(R(t),mid,r);
		
	}
	updata(t);
}
int search(int t,int l,int r)
{
	int mid = MID(seg_tree[t].l,seg_tree[t].r);
	int ll,rr,res_l,res_r;
	if(seg_tree[t].l == l && seg_tree[t].r == r){
		return seg_tree[t].sum;
	}
	if(seg_tree[t].flag == 1){
		
		seg_tree[t].flag = 0;
		
		Swap(L(t));
		
		seg_tree[L(t)].flag ^=1;
		
		Swap(R(t));
		
		seg_tree[R(t)].flag ^=1;
		//updata(t);
	}
	if(r <= mid)return search(L(t),l,r);
	
	else if( l >= mid)return search(R(t),l,r);
	
	else {
		
		res_l = search(L(t),l,mid);
		res_r = search(R(t),mid,r);
		ll = seg_tree[L(t)].r_sum;
		rr = seg_tree[R(t)].l_sum;
		ll = Min(ll,mid-l);
		//printf("<%d>\n",ll);
		rr = Min(rr,r-mid);
		//printf("<%d>\n",rr);
		return Max(ll+rr,Max(res_l,res_r));
		
	}
}
int main()
{
	int n,i,m,x,j;
	while(~scanf("%d",&n)){
		for(i=1;i<=n;i++)scanf("%d",&s[i]);
		build(1,1,n+1);
		scanf("%d",&m);
		while(m--){
			
			scanf("%d%d%d",&x,&i,&j);
			
			if(x==0){
				
				ans = search(1,i,j+1);
				printf("%d\n",ans);
			}
			else insert(1,i,j+1);
		}
		memset(seg_tree,0,sizeof(seg_tree));
	}
	return 0;
}
/*
5
0 1 1 1 0
5
1 3 3
0 1 5
1 1 5
0 1 5
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值