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之间的0变1,1变0
区间合并的模版题,结构体中的lsum1表示从此区间最左端开始连续1的个数,rsum1表示从此区间最右端开始连续1的个数,sum1表示此区间连续1的个数最长是多少。lsum0,rsum0,sum0也是如此。每一次1的操作将区间内lazy标记与1异或一次,异或两次就说明操作抵消了。然后就是细心点就好了。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 1e5 + ;
struct SegTree {
int l , r , lazy;
int lsum1 , rsum1 , sum1;
int lsum0 , rsum0 , sum0;
}T[MAXN << ];
int a[MAXN]; void Pushdown(int p) {
if(T[p].lazy) {
int ls = p << , rs = (p << )|;
T[ls].lazy ^= T[p].lazy;
T[rs].lazy ^= T[p].lazy;
int temp = T[ls].lsum1;
T[ls].lsum1 = T[ls].lsum0;
T[ls].lsum0 = temp;
temp = T[ls].rsum1;
T[ls].rsum1 = T[ls].rsum0;
T[ls].rsum0 = temp;
temp = T[ls].sum1;
T[ls].sum1 = T[ls].sum0;
T[ls].sum0 = temp; temp = T[rs].lsum1;
T[rs].lsum1 = T[rs].lsum0;
T[rs].lsum0 = temp;
temp = T[rs].rsum1;
T[rs].rsum1 = T[rs].rsum0;
T[rs].rsum0 = temp;
temp = T[rs].sum1;
T[rs].sum1 = T[rs].sum0;
T[rs].sum0 = temp; T[p].lazy = ;
}
} void Pushup(int p) {
T[p].lsum1 = T[p << ].lsum1 , T[p].lsum0 = T[p << ].lsum0;
T[p].rsum1 = T[(p << )|].rsum1 , T[p].rsum0 = T[(p << )|].rsum0;
if(T[p].lsum1 == T[p << ].r - T[p << ].l + )
T[p].lsum1 += T[(p << )|].lsum1;
if(T[p].rsum1 == T[(p << )|].r - T[(p << )|].l + )
T[p].rsum1 += T[p << ].rsum1;
if(T[p].lsum0 == T[p << ].r - T[p << ].l + )
T[p].lsum0 += T[(p << )|].lsum0;
if(T[p].rsum0 == T[(p << )|].r - T[(p << )|].l + )
T[p].rsum0 += T[p << ].rsum0;
T[p].sum1 = max(T[p << ].sum1 , max(T[(p << )|].sum1 , T[p << ].rsum1 + T[(p << )|].lsum1));
T[p].sum0 = max(T[p << ].sum0 , max(T[(p << )|].sum0 , T[p << ].rsum0 + T[(p << )|].lsum0));
} void build(int p , int l , int r) {
int mid = (l + r) >> ;
T[p].lazy = ;
T[p].l = l , T[p].r = r;
if(l == r) {
scanf("%d" , a + l);
T[p].sum1 = T[p].lsum1 = T[p].rsum1 = a[l] ? : ;
T[p].sum0 = T[p].lsum0 = T[p].rsum0 = a[l] ? : ;
return ;
}
build(p << , l , mid);
build((p << )| , mid + , r);
Pushup(p);
} void updata(int p , int l , int r , int flag) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
T[p].lazy ^= flag;
int temp = T[p].lsum1;
T[p].lsum1 = T[p].lsum0;
T[p].lsum0 = temp;
temp = T[p].rsum1;
T[p].rsum1 = T[p].rsum0;
T[p].rsum0 = temp;
temp = T[p].sum1;
T[p].sum1 = T[p].sum0;
T[p].sum0 = temp;
return ;
}
Pushdown(p);
if(r <= mid) {
updata(p << , l , r , flag);
}
else if(l > mid) {
updata((p << )| , l , r , flag);
}
else {
updata(p << , l , mid , flag);
updata((p << )| , mid + , r , flag);
}
Pushup(p);
} int query(int p , int l , int r) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
return T[p].sum1;
}
Pushdown(p);
if(r <= mid) {
return query(p << , l , r);
}
else if(l > mid) {
return query((p << )| , l , r);
}
else {
return max( min(T[p << ].rsum1 , mid - l + )+min(T[(p << )|].lsum1 , r - mid) , //mid在l和r之间
max( query(p << , l , mid) , query((p << )| , mid + , r)) );
}
} int main()
{
int n , m , choose , u , v;
while(~scanf("%d" , &n)) {
build( , , n);
scanf("%d" , &m);
while(m--) {
scanf("%d %d %d" , &choose , &u , &v);
if(choose) {
updata( , u , v , );
}
else {
printf("%d\n" , query( , u , v));
}
}
}
return ;
}
HDU 3911 Black And White (线段树区间合并 + lazy标记)的更多相关文章
- HDU 4553 约会安排(线段树区间合并+双重标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 题目大意:就是有三种操作: ①DS x,安排一段长度为x的空闲时间跟屌丝一起,输出这段时间的起点 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- hdu 3911 Black And White(线段树)
题目连接:hdu 3911 Black And White 题目大意:给定一个序列,然后有M次操作: 0 l r:表示询问l,r中最大连续1的个数 1 l r:表示将l,r区间上的数取反 解题思路:线 ...
- HDU 3911 Black and White (线段树,区间翻转)
[题目地址] vjudge HDU [题目大意] 海滩上有一堆石头. 石头的颜色是白色或黑色. 小肥羊拥有魔术刷,她可以改变连续石的颜色,从黑变白,从白变黑. 小肥羊非常喜欢黑色,因此她想知道范围 ...
- HDU 1540 Tunnel Warfare(线段树+区间合并)
http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目大意:抗日战争期间进行地道战,存在n个村庄用地道连接,输入D表示破坏某个村庄(摧毁与其相连的地道, 包 ...
- HDU - 1540 Tunnel Warfare(线段树区间合并)
https://cn.vjudge.net/problem/HDU-1540 题意 D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. 分析 线段树的区间内,我 ...
- hdu 1540 Tunnel Warfare (线段树 区间合并)
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- (简单) HDU 3397 Sequence operation,线段树+区间合并。
Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...
- hdu 3911 Black And White (线段树 区间合并)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...
随机推荐
- chrome浏览器无法设置打开特定网页
最近chrome浏览器更新后,发现以前设置的启动浏览器“重上次停下的地方继续”功能消失了. 当我点击设置网页时,会出现如上提示. 后来有同事给了如下一个连接,里面说到这个是公司的超级管理员搞的,他定义 ...
- 设置MySQL主从同步
1. 配置主服务器 1.1 编辑my.cnf文件,配置主服务器ID. [mysqld] log-bin=mysql-bin server-id=1relay-log = relay-bin relay ...
- HDU3709 Balanced Number (数位dp)
Balanced Number Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Descript ...
- 利用dns解析来实现网站的负载均衡
当网站的访问量大了就会考虑负载均衡,这也是每一个架构师的基本功了,其基本地位就相当于相声里的说学逗唱,活好不好就看这个了 :) 传统的负载均衡思路是单点的,不管你是硬件的还是软件的基本都是这样的原理 ...
- Spring下载
Spring官网改版后找了好久都没有找到直接下载Jar包的链接,下面汇总些网上提供的方法,亲测可用. 1.直接输入地址,改相应版本即可:http://repo.springsource.org/lib ...
- [经验] - JQuery.Ajax + 跨域 (crossDomain) + POST + JSON + WCF RESTful, 5大陷阱和解决方案
最近在开发WSS RESTful服务的时候, 碰到了这些个纠结的问题. 在网上查找了半天, 找到n多种解决方案, 但是都是部分的, 要么是没有跨域的情况, 要么是没有post的情况, 要么不是用WCF ...
- Azure SQL 数据库与新的数据库吞吐量单位
在这一期中,Scott 与 Azure SQL 数据库性能首席项目经理主管 Tobias Ternstrom 一起详细阐释了新的数据库吞吐量单位 (Database Throughput Unit, ...
- 【转】android Apk打包过程概述_android是如何打包apk的
最近看了老罗分析android资源管理和apk打包流程的博客,参考其他一些资料,做了一下整理,脱离繁琐的打包细节和数据结构,从整体上概述了apk打包的整个流程. 流程概述: 1.打包资源文件,生成 ...
- 使用carrierwave出现MiniMagick::Invalid错误的解决方法
安装Imagemagick不能从源码安装,要从软件市场安装,否则会出现错误:MiniMagick::Invalid 使用make uninstall卸载后,重新在软件市场里安装,问题解决.
- .NET之美——.Net 项目代码风格要求
.Net 项目代码风格要求 PDF版下载:项目代码风格要求V1.0.pdf 代码风格没有正确与否,重要的是整齐划一,这是我拟的一份<.Net 项目代码风格要求>,供大家参考. 1. C# ...