题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911

题意:一个01串,两种操作:

0 a b:查询[a,b]内连续1的最长长度。

1 a b:翻转[a,b]内的所有数字(0变1,1变0)。

更新操作落实到具体数字,这时候不能莽直接更新数字对吧,我们要考虑翻转这个操作如何跟懒惰标记对上。让我们可以通过懒惰标记间接更新而不是直接每次更新到叶子。

我们知道一个性质:翻转偶数次相当于没有翻转,那么懒惰标记就来标记翻转次数的奇偶吧,假如是偶数次,那么不需要往下更新了。但是这样的话偶数次解决了,奇数次岂不是还要更新。我们要求连续的1的长度,需要维护一组1的长度(从左起最长、从右起最长、区间内最长),那么再对应地维护一组0的长度,反转的时候相当于这两组数字的交换,每次更新再pushup就没有问题了。

 #include <bits/stdc++.h>
using namespace std; #define lrt rt << 1
#define rrt rt << 1 | 1
typedef struct Node {
int l, r, v;
int lone, sone, rone;
int lzero, szero, rzero;
}Node;
const int maxn = ;
int cmd;
int n, q;
int x[maxn];
Node seg[maxn<<]; void pushUP(int rt, int len) {
seg[rt].lone = seg[lrt].lone; seg[rt].rone = seg[rrt].rone;
seg[rt].lzero = seg[lrt].lzero; seg[rt].rzero = seg[rrt].rzero;
if(seg[rt].lone == len-len/) seg[rt].lone += seg[rrt].lone;
if(seg[rt].rone == len/) seg[rt].rone += seg[lrt].rone;
if(seg[rt].lzero == len-len/) seg[rt].lzero += seg[rrt].lzero;
if(seg[rt].rzero == len/) seg[rt].rzero += seg[lrt].rzero;
seg[rt].sone = max(seg[lrt].sone, seg[rrt].sone);
seg[rt].sone = max(seg[rt].sone, seg[lrt].rone+seg[rrt].lone);
seg[rt].szero = max(seg[lrt].szero, seg[rrt].szero);
seg[rt].szero = max(seg[rt].szero, seg[lrt].rzero+seg[rrt].lzero);
} void pushDOWN(int rt) {
if(seg[rt].v) {
seg[rt].v = ;
seg[lrt].v = !seg[lrt].v;
seg[rrt].v = !seg[rrt].v;
swap(seg[lrt].lone, seg[lrt].lzero);
swap(seg[lrt].rone, seg[lrt].rzero);
swap(seg[lrt].sone, seg[lrt].szero);
swap(seg[rrt].lone, seg[rrt].lzero);
swap(seg[rrt].rone, seg[rrt].rzero);
swap(seg[rrt].sone, seg[rrt].szero);
}
} void build(int l, int r, int rt) {
seg[rt].l = l; seg[rt].r = r; seg[rt].v = ;
if(l == r) {
seg[rt].lone = seg[rt].rone = seg[rt].sone = (x[l] == ) ? : ;
seg[rt].lzero = seg[rt].rzero = seg[rt].szero = (x[l] == ) ? : ;
return;
}
int mid = (l + r) >> ;
build(l, mid, lrt);
build(mid+, r, rrt);
pushUP(rt, r-l+);
} void update(int L, int R, int rt) {
if(L <= seg[rt].l && seg[rt].r <= R) {
swap(seg[rt].lone, seg[rt].lzero);
swap(seg[rt].rone, seg[rt].rzero);
swap(seg[rt].sone, seg[rt].szero);
seg[rt].v = !seg[rt].v;
return;
}
pushDOWN(rt);
int mid = (seg[rt].l + seg[rt].r) >> ;
if(L <= mid) update(L, R, lrt);
if(mid < R) update(L, R, rrt);
pushUP(rt, seg[rt].r-seg[rt].l+);
} int query(int L, int R, int rt) {
if(L == seg[rt].l && R == seg[rt].r) return seg[rt].sone;
pushDOWN(rt);
int mid = (seg[rt].l + seg[rt].r) >> ;
if(mid >= R) return query(L, R, lrt);
else if(mid + <= L) return query(L, R, rrt);
else {
int tmp = max(query(L, mid, lrt), query(mid+, R, rrt));
tmp = max(tmp, min(seg[lrt].rone,mid-L+)+min(seg[rrt].lone,R-mid));
return tmp;
}
} int main() {
//freopen("in", "r", stdin);
int a, b;
while(~scanf("%d", &n)) {
for(int i = ; i <= n; i++) scanf("%d", &x[i]);
build(, n, );
scanf("%d", &q);
while(q--) {
scanf("%d %d %d", &cmd, &a, &b);
if(cmd == ) printf("%d\n", query(a, b, ));
else update(a, b, );
}
}
return ;
}

[HDOJ3911]Black And White(线段树,区间合并)的更多相关文章

  1. 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之间 ...

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

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

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

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

  4. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  5. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  6. HYSBZ 1858 线段树 区间合并

    //Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...

  7. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  8. hdu3911 线段树 区间合并

    //Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  9. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  10. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

随机推荐

  1. Limit the query running time with Resource limit facility (RLF)

    If you need to limit the query(package,plan) running time, but the JCL/JOB TIME parameters doesn't w ...

  2. Javascript与C#编码解码

    (一) Javascript与C#编码解码的对应关系 http://www.jb51.net/article/44062.htm 这篇文章主要是对JS与C#编码解码进行了详细的介绍,需要的朋友可以过来 ...

  3. 重要的事情说三遍:列表 ul / ol 等是块级元素,是块级元素,块级元素

    HTML 块级元素 大多数 HTML 元素被定义为块级元素或内联元素. 编者注:“块级元素”译为 block level element,“行内元素”译为 inline element. 块级元素在浏 ...

  4. Spring+SpringMVC+MyBatis)

    用SSM(Spring.SpringMVC和Mybatis)已经有三个多月了,项目在技术上已经没有什么难点了,基于现有的技术就可以实现想要的功能,当然肯定有很多可以改进的地方.之前没有记录SSM整合的 ...

  5. Hadoop实战4:MapR分布式集群的安装配置及shell自动化脚本

    MapR的分布式集群安装过程还是很艰难的,远远没有计划中的简单.本人总结安装配置,由于集群有很多机器,手动每台配置是很累的,编写了一个自动化配置脚本,下面以脚本为主线叙述(脚本并不完善,后续继续完善中 ...

  6. python False

    None 空字符串 空列表 空元组 空字典 false为False

  7. SQL学习记录

    一些最重要的 SQL 命令 SELECT - 从数据库中提取数据 UPDATE - 更新数据库中的数据 DELETE - 从数据库中删除数据 INSERT INTO - 向数据库中插入新数据 CREA ...

  8. pgadmin(IDE)工具连接postgres数据库

    1. 下载软件        软件地址:http://www.pgadmin.org/download/pgagent.php   2.安装软件    安装过程:略    打开软件64位会出现  “无 ...

  9. git 基本命令

    (命令总结内容来自 博客园  圣骑士Wind的博客) git init      在本地新建一个repo,进入一个项目目录,执行git init,会初始化一个repo,并在当前文件夹下创建一个.git ...

  10. ACM题目————小A的计算器

    Description 以往的操作系统内部的数据表示都是二进制方式,小A新写了一个操作系统,系统内部的数据表示为26进制,其中0-25分别由a-z表示.  现在小A要在这个操作系统上实现一个计算器,这 ...