HDU 3911 Black And White 分段树 题解

来源:互联网 发布:51单片机入门 编辑:程序博客网 时间:2024/06/03 05:27

Problem Description
There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she want to know the longest period of consecutive black stones in a range [i, j].
 

Input
  There are multiple cases, the first line of each case is an integer n(1<= n <= 10^5), followed by n integer 1 or 0(1 indicates black stone and 0 indicates white stone), then is an integer M(1<=M<=10^5) followed by M operations formatted as x i j(x = 0 or 1) , x=1 means change the color of stones in range[i,j], and x=0 means ask the longest period of consecutive black stones in range[i,j]
 

Output
When x=0 output a number means the longest length of black stones in range [i,j].
 

Sample Input
41 0 1 050 1 41 2 30 1 41 3 30 4 4
 

Sample Output
120

分段树依然是难题,本题可以说是分段树的基本操作,但是因为情况好多,程序好长,所以十分耗时间。

之所以使用线段树,不使用一般的动态规划法,是要把每次查询的时间效率降到 (Lgn)。

分段,每段都要维护8个数据,所以很繁琐。

做的好累,代码修改了很多次,最终代码算比较清晰的了。有分段树思想的人应该都不难follow。

Hdu是不允许使用free释放空间的,否则出错,奇怪的OJ。

#pragma once#include <stdio.h>#include <stdlib.h>#include <algorithm>#include <math.h>using namespace std;class BlackAndWhite3911{int arrSize, tSize;int *arr;struct Node{int le0, le1, ri0, ri1;int len0, len1;int totalLen;bool lazy;};Node *SegTree;void updateNode(int r, int L, int R){if (SegTree[L].le0 == SegTree[L].totalLen)SegTree[r].le0 = SegTree[L].le0 + SegTree[R].le0;elseSegTree[r].le0 = SegTree[L].le0;if (SegTree[R].ri0 == SegTree[R].totalLen)SegTree[r].ri0 = SegTree[L].ri0 + SegTree[R].ri0;else SegTree[r].ri0 = SegTree[R].ri0;if (SegTree[L].le1 == SegTree[L].totalLen)SegTree[r].le1 = SegTree[L].le1 + SegTree[R].le1;else SegTree[r].le1 = SegTree[L].le1;if (SegTree[R].ri1 == SegTree[R].totalLen)SegTree[r].ri1 = SegTree[L].ri1 + SegTree[R].ri1;else SegTree[r].ri1 = SegTree[R].ri1;int a = max(SegTree[L].len0, SegTree[R].len0);int b = SegTree[L].ri0 + SegTree[R].le0;SegTree[r].len0 = max(a, b);a = max(SegTree[L].len1, SegTree[R].len1);b = SegTree[L].ri1 + SegTree[R].le1;SegTree[r].len1 = max(a, b);}void conHelper(int low, int up, int r = 0){if (low == up){if (0 == arr[low]){SegTree[r].len0 = 1, SegTree[r].len1 = 0;SegTree[r].le0 = 1, SegTree[r].ri0 = 1;SegTree[r].le1 = 0, SegTree[r].ri1 = 0;}else{SegTree[r].len0 = 0, SegTree[r].len1 = 1;SegTree[r].le0 = 0, SegTree[r].ri0 = 0;SegTree[r].le1 = 1, SegTree[r].ri1 = 1;}SegTree[r].lazy = false;SegTree[r].totalLen = 1;return ;}int mid = low + ((up-low)>>1);int le = (r<<1) + 1;int ri = (r<<1) + 2;conHelper(low, mid, le);conHelper(mid+1, up, ri);SegTree[r].totalLen = up - low + 1;updateNode(r, le, ri);SegTree[r].lazy = false;}void conTree(){int h = (int) ceil(log((double)arrSize)/log(2.0)) + 1;tSize = (int) pow(2.0, h) - 1;SegTree = (Node *) malloc(sizeof(Node) * tSize);conHelper(0, arrSize-1);}void accessNode(int r){SegTree[r].lazy = !SegTree[r].lazy;swap(SegTree[r].le0, SegTree[r].le1);swap(SegTree[r].ri0, SegTree[r].ri1);swap(SegTree[r].len0, SegTree[r].len1);}void segUpdate(const int low, const int up, int L, int R, int r = 0){if (low == L && R == up){accessNode(r);return;}int le = (r<<1) + 1;int ri = (r<<1) + 2;if (SegTree[r].lazy){SegTree[r].lazy = false;if (le < tSize) accessNode(le);if (ri < tSize) accessNode(ri);}int M = L + ((R-L)>>1);if (up <= M) segUpdate(low, up, L, M, le);else if (low > M) segUpdate(low, up, M+1, R, ri);else{segUpdate(low, M, L, M, le);segUpdate(M+1, up, M+1, R, ri);}updateNode(r, le, ri);}int getLongest(const int low, const int up, int L, int R, int r = 0){if (low == L && R == up)//不能low <= L && R <= up{return SegTree[r].len1;}int le = (r<<1) + 1;int ri = (r<<1) + 2;if (SegTree[r].lazy) {SegTree[r].lazy = false;if (le < tSize) accessNode(le);if (ri < tSize) accessNode(ri);}int M = L + ((R-L)>>1);//在任一边子树if (up <= M) return getLongest(low, up, L, M, le);if (low > M) return getLongest(low, up, M+1, R, ri);//跨左右子树的情况int llen = getLongest(low, M, L, M, le);//(low, up, L, M, le);int rlen = getLongest(M+1, up, M+1, R, ri);//(low, up, M+1, R, ri);int a = min(M-low+1, SegTree[le].ri1);int b = min(up-M, SegTree[ri].le1);int c = a + b;return max(c, max(llen, rlen));}public:BlackAndWhite3911(){int N;while ( (scanf("%d", &N) != EOF)){arrSize = N;arr = (int *)malloc(sizeof(int) * arrSize);for (int i = 0; i < N; i++){scanf("%d", &arr[i]);}conTree();int T;scanf("%d", &T);int a, b, c;while (T--){scanf("%d %d %d", &a, &b, &c);if (0 == a)printf("%d\n",getLongest(b-1, c-1, 0, arrSize-1));else segUpdate(b-1, c-1, 0, arrSize-1);}}}~BlackAndWhite3911(){if (arr) free(arr);if (SegTree) free(SegTree);}};



1 0
原创粉丝点击