hdu3911线段树

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

多校(8)

 

题意:给定一个数组元素只有0和1,然后有两种操作,1 i j表示更改[i, j]的所有元素,0 i j表示求[i, j]里面的最长的连续1的串的长度。。。

 

分析:

设置了巨多的参数啊。。。维护了某一段的最左端连续的0个数,连续的1个数,最右端连续0的个数连续1的个数,整段最长的连续0的个数和最长的连续1的个数,然后设置一个标记值cnt,记录该节点更新的次数,每次更新只更新到段,记录到cnt里面,然后每次更新或查找往下找都将cnt往下更新。。。写起来巨繁琐啊。。。

 

纠结了一个下午啊啊啊。。。写起来搞死人。。。漏掉一点点都要郁闷死人。。。特别是求ans那个地方的错误好不容易找到。。

 

巨戳的代码: 再写了一遍,还是不能迅速无误的写出来啊。。。多练手速。。

 

#include<iostream>
using namespace std;

const int N=100010;
int n, m;
struct node
{
	int l, r, mid;
	int max1, max0, llen, rlen;
	bool lcolor, rcolor, cnt;
} a[N*4], tmp1, tmp2;

int _max(int a, int b)
{
	return a>b ? a:b;
}
int _min(int a, int b)
{
	return a<b ? a:b;
}
void build(int l, int r, int p)
{
	a[p].l = l;
	a[p].r = r;
	a[p].mid = (l+r)>>1;
	a[p].max0 = a[p].llen = a[p].rlen = (r-l+1);
	a[p].max1 = 0;
	a[p].lcolor = 0;
	a[p].rcolor = 0;
	a[p].cnt = 0;
	if(l==r)
		return;
	build(l, a[p].mid, p*2);
	build(a[p].mid+1, r, p*2+1);
}

void change(node &a)
{
	if(a.cnt==0)
		return;
	swap(a.max0, a.max1);
	a.lcolor ^= 1;
	a.rcolor ^= 1;
}

void update(int l, int r, int p)
{
	if(a[p].l==l && a[p].r==r)
	{
		a[p].cnt ^= 1;
		return;
	}

	if(a[p].cnt==1)
	{
		a[p*2].cnt ^= a[p].cnt;
		a[p*2+1].cnt ^= a[p].cnt;
		a[p].cnt = 0;
	}

	if(r<=a[p].mid)
		update(l, r, p*2);
	else if(l>a[p].mid)
		update(l, r, p*2+1);
	else
	{
		update(l, a[p].mid, p*2);
		update(a[p].mid+1, r, p*2+1);
	}
	tmp1 = a[p*2];
	tmp2 = a[p*2+1];
	change(tmp1);
	change(tmp2);
	a[p].lcolor = tmp1.lcolor;
	a[p].rcolor = tmp2.rcolor;
	a[p].llen = tmp1.llen;
	a[p].rlen = tmp2.rlen;
	a[p].max0 = _max(tmp1.max0, tmp2.max0);
	a[p].max1 = _max(tmp1.max1, tmp2.max1);
	if(tmp1.rcolor==tmp2.lcolor)
	{
		if(tmp1.llen==tmp1.r-tmp1.l+1)
			a[p].llen += tmp2.llen;
		if(tmp2.rlen==tmp2.r-tmp2.l+1)
			a[p].rlen += tmp1.rlen;
		if(tmp1.rcolor==0)
			a[p].max0 = _max(a[p].max0, tmp1.rlen+tmp2.llen);
		else
			a[p].max1 = _max(a[p].max1, tmp1.rlen+tmp2.llen);
	}
}

int query(int l, int r, int p)
{
	if(a[p].l==l && a[p].r==r)
	{
		if(a[p].cnt==0)
			return a[p].max1;
		else
			return a[p].max0;
	}
	if(a[p].cnt==1)
	{
		a[p*2].cnt ^= a[p].cnt;
		a[p*2+1].cnt ^= a[p].cnt;
	}

	int ans;
	if(r<=a[p].mid)
		ans = query(l, r, p*2);
	else if(l>a[p].mid)
		ans = query(l, r, p*2+1);
	else
	{
		ans = _max(query(l,a[p].mid, p*2), query(a[p].mid+1, r, p*2+1));
		tmp1 = a[p*2];
		tmp2 = a[p*2+1];
		change(tmp1);
		change(tmp2);
		if(tmp1.rcolor==1 && tmp2.lcolor==1)
		{
			int l1, l2;
			l1 = _min(a[p].mid-l+1, tmp1.rlen);
			l2 = _min(r-a[p].mid, tmp2.llen);
			ans = _max(ans, l1+l2);
		}
	}
	if(a[p].cnt==0)
		return ans;

	tmp1 = a[p*2];
	tmp2 = a[p*2+1];
	change(tmp1);
	change(tmp2);
	a[p].lcolor = tmp1.lcolor;
	a[p].rcolor = tmp2.rcolor;
	a[p].llen = tmp1.llen;
	a[p].rlen = tmp2.rlen;
	a[p].max0 = _max(tmp1.max0, tmp2.max0);
	a[p].max1 = _max(tmp1.max1, tmp2.max1);
	if(tmp1.rcolor==tmp2.lcolor)
	{
		if(tmp1.llen==tmp1.r-tmp1.l+1)
			a[p].llen += tmp2.llen;
		if(tmp2.rlen==tmp2.r-tmp2.l+1)
			a[p].rlen += tmp1.rlen;
		if(tmp1.rcolor==0)
			a[p].max0 = _max(a[p].max0, tmp1.rlen+tmp2.llen);
		else
			a[p].max1 = _max(a[p].max1, tmp1.rlen+tmp2.llen);
	}
	a[p].cnt = 0;
	return ans;
}

int main()
{
	int i, j, k, op, x, y;
	while(scanf("%d", &n)!=EOF)
	{
		build(1, n, 1);
		for(i=1; i<=n; i++)
		{
			scanf("%d", &x);
			if(x==1)
				update(i, i, 1);
		}
		scanf("%d", &m);
		while(m--)
		{			
			scanf("%d%d%d", &op, &x, &y);
			if(op==0)
				printf("%d\n", query(x, y, 1));
			else
				update(x, y, 1);
		}
	}

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章