题目链接: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. Angularjs之controller 和filter(四)

    Controller组件(http://www.angularjs.cn/A00C) 在AngularJS中,控制器是一个Javascript函数(类型/类),用来增强除了根作用域以外的作用域实例的. ...

  2. ORA-000845 与 /dev/shm(tempfs)

    MEMORY_TARGET参数在Oracle 11g被引进,主要是用于控制Oracle对于系统内存的使用,首次将SGA与PGA整合到一起实现自动管理.一旦设置了MEMORY_TARGET参数值,Ora ...

  3. OBD 14230 Slow, Addr激活

    const u8 LinkCmd14230[6] = { 0xC2, 0x33, 0xF1, 0x01, 0x00, 0xE7 }; u8 ISO14230ADDR_Check(){          ...

  4. linux下xargs命令用法详解 【转】

    转自:http://blog.chinaunix.net/uid-128922-id-289992.html xargs在linux中是个很有用的命令,它经常和其他命令组合起来使用,非常的灵活. xa ...

  5. js笔记----(运动)分享 隐藏/显示

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  6. stl map底层之红黑树插入步骤详解与代码实现

    转载注明出处:http://blog.csdn.net/mxway/article/details/29216199 本篇文章并没有详细的讲解红黑树各方面的知识,只是以图形的方式对红黑树插入节点需要进 ...

  7. hdu4924 Football Manager

    这题上来我是没有思路的.因为目标值关涉到的因素太多而直接枚举的复杂度又太高. 目标值由两部分合成,一部分是队员的CA和与PA和,另一部分是队员之间的relationship. 前者是简单的代数累加,而 ...

  8. 【linux命令与工具】ethtool命令

    ethtool是用于查询及设置网卡参数的命令. 如果command not found可以用apt-get/yum添加. 主要参数: ethtool ethX//查看ethX设备属性 ethtool ...

  9. phpcms 02

    头部和尾部包含 1 默认的首页模板 C:\wamp\www\phpcms\templates\ypzy2014\content\index.html 打开模板查看 第一句 {template &quo ...

  10. HDU 4810 Wall Painting

    Wall Painting Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...