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;
}


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