现在的位置: 首页 > 综合 > 正文

HDOJ 3911 Black And White 线段树 区间合并 成段更新

2014年01月03日 ⁄ 综合 ⁄ 共 2468字 ⁄ 字号 评论关闭
//HDOJ 3911 Black And White 线段树 区间合并 成段更新

/*
题意:有一堆黑、白球排成一排,有两种操作:
	  1:将一段连续的球改变颜色,黑色变成白色,白色变成黑色
	  2:查询一段区间内连续的黑色的球的个数
	
思路:每个结点记录7个信息:
	  lsum0:从左端开始的连续的白球个数
	  rsum0:从右端开始的连续的白球个数
	  msum0:区间内连续的白球的最大个数
	  lsum1:从左端开始的连续的黑球个数
	  rsum1:从右端开始的连续的黑球个数
	  msum1:区间内连续的黑球的最大个数
	  add:是否向下更新

	  进行操作1的时候只要将黑球白球的各种信息交换	
*/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define N 100005
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r

int n,m;
int lsum0[N<<2],rsum0[N<<2],msum0[N<<2];
int lsum1[N<<2],rsum1[N<<2],msum1[N<<2];
int sum[N<<2],add[N<<2];

int Max(int x,int y){
	return x>y?x:y;
}

void swap(int &x,int &y){
	int tmp = x;
	x = y;
	y = tmp;
}

void Pushup(int rt,int m){
	lsum0[rt] = lsum0[rt<<1];
	rsum0[rt] = rsum0[rt<<1|1];
	if(lsum0[rt] == m-(m>>1)) lsum0[rt] += lsum0[rt<<1|1];
	if(rsum0[rt] == (m >> 1)) rsum0[rt] += rsum0[rt<<1];
	msum0[rt] = Max(rsum0[rt<<1]+lsum0[rt<<1|1],Max(msum0[rt<<1],msum0[rt<<1|1]));
	
	lsum1[rt] = lsum1[rt<<1];
	rsum1[rt] = rsum1[rt<<1|1];
	if(lsum1[rt] == m-(m>>1)) lsum1[rt] += lsum1[rt<<1|1];
	if(rsum1[rt] == (m >> 1)) rsum1[rt] += rsum1[rt<<1];
	msum1[rt] = Max(rsum1[rt<<1]+lsum1[rt<<1|1],Max(msum1[rt<<1],msum1[rt<<1|1]));
}

void Pushdown(int rt){
	if(add[rt]){
		add[rt<<1] ^= 1;
		add[rt<<1|1] ^= 1;
		swap(lsum0[rt<<1],lsum1[rt<<1]);
		swap(rsum0[rt<<1],rsum1[rt<<1]);
		swap(msum0[rt<<1],msum1[rt<<1]);
		swap(lsum0[rt<<1|1],lsum1[rt<<1|1]);
		swap(rsum0[rt<<1|1],rsum1[rt<<1|1]);
		swap(msum0[rt<<1|1],msum1[rt<<1|1]);
		add[rt] = 0;
	}
}

void Build(int rt,int l,int r){
	if(l == r){
		int x;
		scanf("%d",&x);
		lsum1[rt] = rsum1[rt] = msum1[rt]= x;
		lsum0[rt] = rsum0[rt] = msum0[rt] = 1-x;
		return ;
	}
	int mid = (l + r) >> 1;
	Build(lson);
	Build(rson);
	Pushup(rt,r-l+1);
}

void Update(int rt,int l,int r,int L,int R){
	if(L <= l && R >= r){
		swap(lsum0[rt],lsum1[rt]);
		swap(rsum0[rt],rsum1[rt]);
		swap(msum0[rt],msum1[rt]);
		add[rt]^=1;
		return ;
	}
	Pushdown(rt);
	int mid = (l + r) >> 1;
	if(L <= mid) Update(lson,L,R);
	if(R > mid ) Update(rson,L,R);
	Pushup(rt,r-l+1);
}

int Query(int rt,int l,int r,int L,int R){
	if(L <= l && R >= r){
		return msum1[rt];
	}
	Pushdown(rt);
	int s1=0,s2=0,s3=0;
	int mid = (l + r) >> 1;
	if(L <= mid) s1 = Query(lson,L,R);
	if(R > mid ) s2 = Query(rson,L,R);
	if(L <= mid && R > mid){
		if(rsum1[rt<<1] <= mid-L+1)	s3 += rsum1[rt<<1];
		else						s3 += mid-L+1;
		if(lsum1[rt<<1|1] <= R-mid)	s3 += lsum1[rt<<1|1];
		else						s3 += R-mid;
	}
	return Max(s3,Max(s1,s2));
}

int main(){
	int op,a,b;
	while(scanf("%d",&n)!=EOF){
		memset(lsum0,0,sizeof(lsum0));
		memset(rsum0,0,sizeof(rsum0));
		memset(msum0,0,sizeof(msum0));
		memset(lsum1,0,sizeof(lsum1));
		memset(rsum1,0,sizeof(rsum1));
		memset(msum1,0,sizeof(msum1));
		memset(add,0,sizeof(add));
		Build(1,1,n);
		scanf("%d",&m);
		while(m--){
			scanf("%d %d %d",&op,&a,&b);
			if(op == 1){
				Update(1,1,n,a,b);
			}
			else{
				printf("%d\n",Query(1,1,n,a,b));
			}
		}
	}
	return 0;
}

抱歉!评论已关闭.