首页 > 代码库 > HDU 3911 Black And White 分段树 题解
HDU 3911 Black And White 分段树 题解
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
4 1 0 1 0 5 0 1 4 1 2 3 0 1 4 1 3 3 0 4 4
Sample Output
1 2 0
分段树依旧是难题,本题能够说是分段树的基本操作,可是由于情况好多,程序好长,所以十分耗时间。
之所以使用线段树,不使用一般的动态规划法,是要把每次查询的时间效率降到 (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; else SegTree[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); } };
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。