[HDOJ3911]Black And White(线段树,区间合并)
题目链接: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(线段树,区间合并)的更多相关文章
- 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之间 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- hdu 3911 Black And White (线段树 区间合并)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HYSBZ 1858 线段树 区间合并
//Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- hdu3911 线段树 区间合并
//Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- 线段树(区间合并) POJ 3667 Hotel
题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...
随机推荐
- OpenGL笔试题
简述FrameBuffer,RenderBuffer,Depth Buffer,Framebuffer attachment,Stencil buffer的关系 简述利用OpenGL执行图像叠加(大P ...
- Inside TSQL Querying - Chapter 2. Physical Query Processing
Summary Description The SQL language is spoken by most database experts, and all relational database ...
- 项目发布时候出错--项目文件包含 ToolsVersion="12.0"
项目文件包含 ToolsVersion="12.0".此工具集可能未知或缺失(您可以通过安装相应版本的 MSBuild 来解决该问题),或者该生成因策略原因已被强制更改为特殊 To ...
- 如何从innodb的数据字典里恢复表结构
需要学会使用percona-data-recovery-tool-for-innodb,用这个:sys_parser,参考这篇文章,
- PayPal网站付款标准版(for PHP)
简单整理一下PHP项目整合PayPal支付功能. 一.表单的构建: <form method="post" name="form" action=&quo ...
- mmap直接控制底层【转】
转自:http://blog.csdn.net/xyyangkun/article/details/7830149 版权声明:本文为博主原创文章,未经博主允许不得转载. 这是在mini6410上测试成 ...
- Hibernate,JPA注解@EmbeddedId
定义组合主键的几种语法: 将组件类注解为@Embeddable,并将组件的属性注解为@Id 将组件的属性注解为@EmbeddedId 将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为 ...
- Hibernate,JPA注解@Version
Hibernate实现悲观锁和乐观锁. 1,悲观锁 用例代码如下: 数据库DDL语句: hibernate.cfg.xml java类 以上代码(除下面的main之外)同乐观锁. main packa ...
- [ios]iOS 图形编程总结
转自:http://www.cocoachina.com/ios/20141104/10124.html iOS实现图形编程可以使用三种API(UIKIT.Core Graphics.OpenGL E ...
- [ios][swift]提示框,并自动消失
参考: 提示框:http://blog.csdn.net/gishero/article/details/43941361 提示框自动消失:http://www.cnblogs.com/yemingl ...