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

HDU 3911 Black And White 分段树 题解的更多相关文章

  1. hdu 3911 Black And White(线段树)

    题目连接:hdu 3911 Black And White 题目大意:给定一个序列,然后有M次操作: 0 l r:表示询问l,r中最大连续1的个数 1 l r:表示将l,r区间上的数取反 解题思路:线 ...

  2. HDU 3911 Black and White (线段树,区间翻转)

      [题目地址] vjudge HDU [题目大意] 海滩上有一堆石头. 石头的颜色是白色或黑色. 小肥羊拥有魔术刷,她可以改变连续石的颜色,从黑变白,从白变黑. 小肥羊非常喜欢黑色,因此她想知道范围 ...

  3. HDU 3911 Black And White (线段树区间合并 + lazy标记)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911 给你n个数0和1,m个操作: 0操作  输出l到r之间最长的连续1的个数 1操作  将l到r之间 ...

  4. hdu 3911 Black And White (线段树 区间合并)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...

  5. HDU 3911 Black And White(线段树区间合并+lazy操作)

    开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...

  6. HDU 3911 Black And White

    Black And White Time Limit: 3000ms Memory Limit: 32768KB This problem will be judged on HDU. Origina ...

  7. HDU 1556 Color the Ball 线段树 题解

    本题使用线段树自然能够,由于区间的问题. 这里比較难想的就是: 1 最后更新须要查询全部叶子节点的值,故此须要使用O(nlgn)时间效率更新全部点. 2 截取区间不能有半点差错.否则答案错误. 这两点 ...

  8. HDU 6089 Rikka with Terrorist (线段树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6089 题解 这波强行维护搞得我很懵逼... 扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左 ...

  9. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

随机推荐

  1. 给VS自动添加注释

    找到类文件所在路径:C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplatesCache\CSharp\ ...

  2. char s[]字串和char *s字串有什麼区别?

    C語言有兩種字串宣告方式char s[]和char *s,兩者有什麼差異呢? Introduction char s[] = "Hello World"; (只是用字符串常量初始化 ...

  3. Makefile学习(二)[第二版]

    复杂实例 #演示样例1:在上一个演示样例的基础上再添加一个可运行文件03test[改动之处已标红] .PHONY: clean all CC = gcc CFLAGS = -Wall -g BIN = ...

  4. 安装DBMS_SHARED_POOL包

    在安装10g gc的时候,会遇到The DBMS_SHARED_POOL package is not executed on the Existing Database这样的一个错误,意思是提示你D ...

  5. [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传

    原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...

  6. 反应堆Reactor

    mvn -h 可以看到很多命令及其用途:-am --also-make 同时构建所列模块的依赖模块:-amd -also-make-dependents 同时构建依赖于所列模块的模块:-pl --pr ...

  7. skip32

    在某些应用场景下,需要对数字进行加密,skip32无疑是一种很实用的算法,网上有python的源码(https://bitbucket.org/anuraguniyal/skip32.py/src/4 ...

  8. __sleep和__wakeup

    魔术方法__sleep和__wakeup 串行化serialize可以把变量包括对象,转化成连续bytes数据. 你可以将串行化后的变量存在一个文件里或在网络上传输. 然后再反串行化还原为原来的数据. ...

  9. SRM 223 Div II Level Two: BlackAndRed,O(N)复杂度

    题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=3457&rd=5869 解答分析:http://comm ...

  10. [置顶] Windows Phone后台音乐详解一

    应用于: Windows Phone 8 | Windows PhoneOS 7.1 你可以为winphone编写在后台播放音乐的app.这表示即使当用户点击返回或开始按钮离开你的应用界面时,你的应用 ...