hdu3397----Sequence operation

Sequence operation

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6503    Accepted Submission(s): 1937


Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.
We have five operations here:
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
 

Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, '0' or '1' separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
 

Output
For each output operation , output the result.
 

Sample Input
   
   
   
   
1 10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
 

Sample Output
   
   
   
   
5 2 6 5
 

Author
lxhgww&&shǎ崽
 

Source
HDOJ Monthly Contest – 2010.05.01

这题要维护的东西很多, 区间左边连续1的个数,区间右边连续1的个数, 区间最长连续1的长度,区间1的个数,区间左边连续0个数,区间右边连续0个数,区间最长连续0长度,区间0的个数,还有延迟标记

对于延迟标记:如果原来没标记,那么把现在的标记覆盖上去
如果现在的标记是0或1 (把区间变成0或1),无论之前是什么,直接覆盖上去
 如果现在的标记是2(翻转), 之前是2,那么2次翻转等于没翻,标记清掉,之前是0,  那么先把区间变成0,再翻转,相当于把区间变成1,也就是标记1
之间是1,那么先把区间变成1,再翻转,相当于把区间变成0,也就是标记0,有了这些就好写了

/*************************************************************************
    > File Name: hdu3397.cpp
    > Author: ALex
    > Mail: [email protected] 
    > Created Time: 2015年01月11日 星期日 12时51分06秒
 ************************************************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int sta[N];

struct node
{
	int l, r;
	int cnt0, cnt1;
	int l1, r1, l0, r0;
	int len1, len0;
	int add;
}tree[N << 2];

void pushup (int p)
{
	tree[p].l1 = tree[p << 1].l1;
	tree[p].r1 = tree[p << 1 | 1].r1;
	tree[p].cnt1 = tree[p << 1].cnt1 + tree[p << 1 | 1].cnt1;
	if (tree[p << 1].l1 == tree[p << 1].r - tree[p << 1].l + 1)
	{
		tree[p].l1 += tree[p << 1 | 1].l1;
	}
	if (tree[p << 1 | 1].r1 == tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1)
	{
		tree[p].r1 += tree[p << 1].r1;
	}
	tree[p].len1 = max( max(tree[p << 1].len1, tree[p << 1 | 1].len1), tree[p << 1].r1 + tree[p << 1 | 1].l1 );
	tree[p].l0 = tree[p << 1].l0;
	tree[p].r0 = tree[p << 1 | 1].r0;
	tree[p].cnt0 = tree[p << 1].cnt0 + tree[p << 1 | 1].cnt0;
	if (tree[p << 1].l0 == tree[p << 1].r - tree[p << 1].l + 1)
	{
		tree[p].l0 += tree[p << 1 | 1].l0;
	}
	if (tree[p << 1 | 1].r0 == tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1)
	{
		tree[p].r0 += tree[p << 1].r0;
	}
	tree[p].len0 = max ( max(tree[p << 1].len0, tree[p << 1 | 1].len0), tree[p << 1].r0 + tree[p << 1 | 1].l0 );
}

void pushdown (int p)
{
	if (tree[p].add != -1)
	{
		if (tree[p].add == 0) //把区间变成0
		{
			tree[p << 1].len1 = tree[p << 1].l1 = tree[p << 1].r1 = tree[p << 1].cnt1 = 0;
			tree[p << 1].len0 = tree[p << 1].l0 = tree[p << 1].r0 = tree[p << 1].cnt0 = tree[p << 1].r - tree[p << 1].l + 1;
			tree[p << 1 | 1].len1 = tree[p << 1 | 1].l1 = tree[p << 1 | 1].r1 = tree[p << 1 | 1].cnt1 = 0;
			tree[p << 1 | 1].len0 = tree[p << 1 | 1].l0 = tree[p << 1 | 1].r0 = tree[p << 1 | 1].cnt0 = tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1;
			tree[p << 1].add = 0;
			tree[p << 1 | 1].add = 0;
		}
		else if (tree[p].add == 1) //把区间变成1
		{
			tree[p << 1].len1 = tree[p << 1].l1 = tree[p << 1].r1 = tree[p << 1].cnt1 = tree[p << 1].r - tree[p << 1].l + 1;
			tree[p << 1].len0 = tree[p << 1].l0 = tree[p << 1].r0 = tree[p << 1].cnt0 = 0;
			tree[p << 1 | 1].len1 = tree[p << 1 | 1].l1 = tree[p << 1 | 1].r1 = tree[p << 1 | 1].cnt1 = tree[p << 1 | 1].r - tree[p << 1 | 1].l + 1;
			tree[p << 1 | 1].len0 = tree[p << 1 | 1].l0 = tree[p << 1 | 1].r0 = tree[p << 1 | 1].cnt0 = 0;
			tree[p << 1].add = 1;
			tree[p << 1 | 1].add = 1;
		}
		else
		{
			swap (tree[p << 1].len1, tree[p << 1].len0);
			swap (tree[p << 1].l1, tree[p << 1].l0);
			swap (tree[p << 1].r1, tree[p << 1].r0);
			swap (tree[p << 1].cnt1, tree[p << 1].cnt0);
			swap (tree[p << 1 | 1].len1, tree[p << 1 | 1].len0);
			swap (tree[p << 1 | 1].l1, tree[p << 1 | 1].l0);
			swap (tree[p << 1 | 1].r1, tree[p << 1 | 1].r0);
			swap (tree[p << 1 | 1].cnt1, tree[p << 1 | 1].cnt0);
			if (tree[p << 1].add == -1)
			{
				tree[p << 1].add = 2;
			}
			else if (tree[p << 1].add == 2)
			{
				tree[p << 1].add = -1;
			}
			else if (tree[p << 1].add == 0)
			{
				tree[p << 1].add = 1;
			}
			else
			{
				tree[p << 1].add = 0;
			}
			if (tree[p << 1 | 1].add == -1)
			{
				tree[p << 1 | 1].add = 2;
			}
			else if (tree[p << 1 | 1].add == 2)
			{
				tree[p << 1 | 1].add = -1;
			}
			else if (tree[p << 1 | 1].add == 0)
			{
				tree[p << 1 | 1].add = 1;
			}
			else
			{
				tree[p << 1 | 1].add = 0;
			}
		}
		tree[p].add = -1;
	}
}

void build (int p, int l, int r)
{
	tree[p].l = l;
	tree[p].r = r;
	tree[p].add = -1;
	if (l == r)
	{
		if (sta[l])
		{
			tree[p].l1 = tree[p].r1 = tree[p].len1 = 1;
			tree[p].l0 = tree[p].r0 = tree[p].len0 = 0;
			tree[p].cnt0 = 0;
			tree[p].cnt1 = 1;
		}
		else
		{
			tree[p].l1 = tree[p].r1 = tree[p].len1 = 0;
			tree[p].l0 = tree[p].r0 = tree[p].len0 = 1;
			tree[p].cnt0 = 1;
			tree[p].cnt1 = 0;
		}
		return;
	}
	int mid = (l + r) >> 1;
	build (p << 1, l, mid);
	build (p << 1 | 1, mid + 1,r);
	pushup (p);
}

void update (int p, int l, int r, int x)
{
	if (l == tree[p].l && tree[p].r == r)
	{
		if (x == 0)
		{
			tree[p].l0 = tree[p].r0 = tree[p].len0 = tree[p].cnt0 = tree[p].r - tree[p].l + 1;
			tree[p].l1 = tree[p].r1 = tree[p].len1 = tree[p].cnt1 = 0;
			tree[p].add = 0;
		}
		else if (x == 1)
		{
			tree[p].l0 = tree[p].r0 = tree[p].len0 = tree[p].cnt0 = 0;
			tree[p].l1 = tree[p].r1 = tree[p].len1 = tree[p].cnt1 = tree[p].r - tree[p].l + 1;
			tree[p].add = 1;
		}
		else
		{
			swap (tree[p].l1, tree[p].l0);
			swap (tree[p].r1, tree[p].r0);
			swap (tree[p].len1, tree[p].len0);
			swap (tree[p].cnt1, tree[p].cnt0);
			if (tree[p].add == -1)
			{
				tree[p].add = 2;
			}
			else if (tree[p].add == 2)
			{
				tree[p].add = -1;
			}
			else if (tree[p].add == 1)
			{
				tree[p].add = 0;
			}
			else
			{
				tree[p].add = 1;
			}
		}
		return;
	}
	pushdown (p);
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (r <= mid)
	{
		update (p << 1, l, r, x);
	}
	else if (l > mid)
	{
		update (p << 1 | 1, l, r, x);
	}
	else
	{
		update (p << 1, l, mid, x);
		update (p << 1 | 1, mid + 1, r, x);
	}
	pushup (p);
//	printf("区间[%d, %d] 左边1 %d, 右边1 %d, 左边0 %d, 右边0 %d, 1个数 %d, 0个数 %d\n", tree[p].l, tree[p].r, tree[p].l1, tree[p].r1, tree[p].l0, tree[p].r0, tree[p].cnt1, tree[p].cnt0);

}

int query (int p, int l, int r, int x)
{
	if (tree[p].l == l && tree[p].r == r)
	{
		if (x == 3)
		{
			return tree[p].cnt1;
		}
		else
		{
			return tree[p].len1;
		}
	}
	pushdown (p);
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (r <= mid)
	{
		return query (p << 1, l, r, x);
	}
	else if (l > mid)
	{
		return query (p << 1 | 1, l, r, x);
	}
	else
	{
		if (x == 3)
		{
			return query (p << 1, l, mid, x) + query (p << 1 | 1, mid + 1, r, x);
		}
		else
		{
			int ret = 0; 
			if (l >= mid - tree[p << 1].r1 + 1 && r <= mid + tree[p << 1 | 1].l1)
			{
				ret = r - l + 1;
			}
			else if (l < mid - tree[p << 1].r1 + 1 && r <= mid + tree[p << 1 | 1].l1)
			{
				int s = mid - tree[p << 1].r1 + 1;
				ret = max (r - s + 1, query (p << 1, l, mid, x));
			}
			else if (l >= mid - tree[p << 1].r1 + 1 && r > mid + tree[p << 1 | 1].l1)
			{
				int e = mid + tree[p << 1 | 1].l1;
				ret = max (e - l + 1, query (p << 1 | 1, mid + 1, r, x));
			}
			else
			{
				ret = max(tree[p << 1 | 1].l1 + tree[p << 1].r1, max(query (p << 1, l, mid, x), query (p << 1 | 1, mid + 1, r, x)));
			}
			return ret;
		}
	}
}

int main()
{
	int t;
	int x, l, r;
	scanf("%d", &t);
	while (t--)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n; ++i)
		{
			scanf("%d", &sta[i]);
		}
		build (1, 0, n - 1);
		while (m--)
		{
			scanf("%d%d%d", &x, &l, &r);
			if (x >= 0 && x <= 2)
			{
				update (1, l, r, x);
			}
			else
			{
				printf("%d\n", query (1, l, r, x));
			}
		}
	}
	return 0;

}


你可能感兴趣的:(线段树)