题目链接: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. 某硕笔试题mysql数据库部分(较为全面)

    Student(S#,Sname,Sage,Ssex) 学生表  Course(C#,Cname,T#) 课程表  SC(S#,C#,score) 成绩表  Teacher(T#,Tname) 教师表 ...

  2. innodb的锁到底占用多少内存

    举个简单的例子: CREATE TABLE `sample` ( `i` ) unsigned NOT NULL auto_increment, `j` ) default NULL, PRIMARY ...

  3. ExtJS4.2 根据数据库记录构建树形菜单

    背景:最近用ExtJS4.2做一个系统,需要在前端展示资源菜单,为树形结构,该树形结构是从数据库动态加载的. ExtJS的树形结构大致有两种情况: 1.静态树形结构,此处不多说,看API就能简单明白: ...

  4. jQuery的Ajax的跨域请求

    今天碰到一个Ajax跨域请求的问题,我把源码down下来,然后在服务器端写了一个http请求的代理(因为服务器端是不存在跨域问题的),说白了就是用BufferedReader写了个IO流,然后读取到目 ...

  5. 新增PHP经典笔记

    [设置编码] header("Content-type: text/html; charset=utf-8"); 1. parse_url - 解析 URL,返回其组成部分 $ua ...

  6. 多线程并发流程控制之dispatch_group 有关函数

    A B C D 4个并发下载任务,怎样在第一时间知道任务全部完成? dispatch_group 可以帮我们实现这样的控制. 上代码,看说明. dispatch_group_t group = dis ...

  7. android应用的数据应该保存到哪儿

    王永超王永超嫖娼 做android app开发会涉及到不同数据的保存,比如数据缓存,客户登陆信息保存,客户状态的保存等等. 那针对这不同的数据我们应该保存在什么地方呢? 1.应用卸载也不会删除的数据 ...

  8. LeetCode----204. Count Primes(Java)

    package countPrimes204; /* * Description: * Count the number of prime numbers less than a non-negati ...

  9. 杭电1097-A hard puzzle

    Problem Description lcy gives a hard puzzle to feng5166,lwg,JGShining and Ignatius: gave a and b,how ...

  10. [转]application windows are expected to have a root view controller错误

    转载地址:http://blog.sina.com.cn/s/blog_6784e6ea01017jfy.html 最新更正:这个提示几乎不影响编译和运行,可以不用设置.     产生这个提示的操作: ...