HDU 3911 Black and White (线段树,区间翻转)
【题目地址】
【题目大意】
- 海滩上有一堆石头。 石头的颜色是白色或黑色。 小肥羊拥有魔术刷,她可以改变连续石的颜色,从黑变白,从白变黑。 小肥羊非常喜欢黑色,因此她想知道范围[i,j]中连续的黑色石头的最长时间。
- 有多种情况,每种情况的第一行是整数n(1 <= n <= 10 ^ 5),后跟n个整数1或0(1表示黑石头,0表示白石头),然后是整数 M(1 <= M <= 10 ^ 5)后跟M个运算,格式为xij(x = 0或1),x = 1表示更改范围[i,j]中的石头颜色,并且x = 0表示询问 [i,j]范围内连续黑宝石的最长时间
- 当x = 0输出时,数字表示范围为[i,j]的黑色宝石的最长长度。
【样例输入】
4
1 0 1 0
5
0 1 4
1 2 3
0 1 4
1 3 3
0 4 4
【样例输出】
1
2
0
【一句话题意】
- 操作指令为0:
查询【L, R】中最长的连续的1的个数
- 操作指令为1:
将区间【L, R】中的0和1翻转
【难点】
没办法一步到位求得连续1的个数,如果强买强卖,就是暴力,我们的良心会受到谴责
【突破】逆推,运用分治的思想化繁为简
1.我们想要维护区间最长连续1的个数,只需要知道每个子区间内最大前缀1,
最大后缀1(原因先自己思考下)
2.想要维护答案和上述两个后缀长度,并且包含修改操作,那么可以去维护对应的0的个数,
即区间最长连续0的个数,区间最大前缀0,最大后缀0
3.众所周知,区间修改需要lazytag(懒标记)
4.(此时没明白不打紧,先往后看)
【思路梳理】
一、需要维护的7个变量:
区间最大前缀1
区间最大前缀0
区间最大后缀1
区间最大后缀0
区间最大连续1
区间最大连续0
懒惰标记
二、修改操作
向下更改时交换所有0,1相关值
三、查询
分割区间
计算左子区间最大后缀1与当前区间最大前缀1
计算右子区间最大前缀1与当前区间最大后缀1
将2、3条取max即为所求
四、注意细节,代码实现
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define int long long
using namespace std; inline int read(){
int x = , w = ;
char ch = getchar();
for(; ch > '' || ch < ''; ch = getchar()) if(ch == '-') w = -;
for(; ch >= '' && ch <= ''; ch = getchar()) x = x * + ch - '';
return x * w;
} const int maxn = ;
int a[maxn]; struct node{
int l0, r0;
int l1, r1;
int max0, max1;
int lazytag;
}tree[maxn << ]; inline void solve(int u, int l, int r){//维护7个相关值
int mid = (l + r) >> ;
//前缀1
tree[u].l1 = tree[u << ].l1;
if(tree[u].l1 == mid - l + ){
tree[u].l1 += tree[u << | ].l1;
}
//前缀0
tree[u].l0 = tree[u << ].l0;
if(tree[u].l0 == mid - l + ){
tree[u].l0 += tree[u << | ].l0;
}
//后缀1
tree[u].r1 = tree[u << | ].r1;
if(tree[u].r1 == r - mid){
tree[u].r1 += tree[u << ].r1;
}
//后缀0
tree[u].r0 = tree[u << | ].r0;
if(tree[u].r0 == r - mid){
tree[u].r0 += tree[u << ].r0;
}
//区间最大1,最大0
tree[u].max1 = max (max (tree[u << ].max1, tree[u << | ].max1), tree[u << ].r1 + tree[u << | ].l1);
tree[u].max0 = max (max (tree[u << ].max0, tree[u << | ].max0), tree[u << ].r0 + tree[u << | ].l0);
} inline void SWAP(int u){//保留备用,每次做区间翻转的时候要用
swap(tree[u].l0, tree[u].l1);
swap(tree[u].r0, tree[u].r1);
swap(tree[u].max0, tree[u].max1);
} inline void pushdown(int u, int l, int r){//懒标记下防
if(l != r){
tree[u << ].lazytag ^= ;
tree[u << | ].lazytag ^= ;
SWAP(u << );
SWAP(u << | );
tree[u].lazytag = ;
}
} int tmp;
inline void build(int u, int l, int r){//建树
tree[u].lazytag = ;
if(l == r){
tmp = read();
if(tmp == ){//若当前石头为黑色
tree[u].l1 = tree[u].r1 = tree[u].max1 = ;
tree[u].l0 = tree[u].r0 = tree[u].max0 = ;
}
else{//为白色
tree[u].l1 = tree[u].r1 = tree[u].max1 = ;
tree[u].l0 = tree[u].r0 = tree[u].max0 = ;
}
return;
}
int mid = (l + r) >> ;
build(u << , l, mid);//左子树
build(u << | , mid + , r);//右子树
solve(u, l, r);//维护7个相关值
} inline void change(int u, int l, int r, int s, int t){//区间翻转
if(l >= s && r <= t){//更新lazytag
tree[u].lazytag ^= ;
SWAP(u);
return;
}
if(tree[u].lazytag) pushdown(u, l, r);
int mid = (l + r) >> ;
if(mid >= t)
update(u << , l, mid, s, t);
else if(mid < s)
update(u << | , mid + , r, s, t);
else{
update(u << , l, mid, s, t);
update(u << | , mid + , r, s, t);
}
solve(u, l, r);//维护7个相关值
} inline int query(int u, int l, int r, int s, int t){
if(l >= s && r <= t){
return tree[u].max1;
}
if(tree[u].lazytag) pushdown(u, l ,r);
int mid = (l + r) >> ;
if(mid >= t) return query(u << , l, mid, s, t);
else if(mid < s) return query(u << | , mid + , r, s, t);
else{
int cnt1 = query(u << , l, mid, s, t);
int cnt2 = query(u << | , mid + , r, s, t);
int cnt3 = min(mid - s + , tree[u << ].r1);
int cnt4 = min(t - mid, tree[u << | ].l1);
return max(max(cnt1, cnt2), cnt3 + cnt4);
}
solve(u, l, r);
} signed main(){
int n;
while(scanf("%lld", &n) == ){
build(, , n);
int m = read();
while(m--){
int opt = read(), l = read(), r = read();
if(opt == )//翻转
change(, , n, l, r);
else//查询
printf("%lld\n", query(, , n, l, r));
}
}
return ;
}
HDU 3911
HDU 3911 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(线段树)
题目连接:hdu 3911 Black And White 题目大意:给定一个序列,然后有M次操作: 0 l r:表示询问l,r中最大连续1的个数 1 l r:表示将l,r区间上的数取反 解题思路:线 ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU.1689 Just a Hook (线段树 区间替换 区间总和)
HDU.1689 Just a Hook (线段树 区间替换 区间总和) 题意分析 一开始叶子节点均为1,操作为将[L,R]区间全部替换成C,求总区间[1,N]和 线段树维护区间和 . 建树的时候初始 ...
- HDU 1698 Just a Hook(线段树 区间替换)
Just a Hook [题目链接]Just a Hook [题目类型]线段树 区间替换 &题解: 线段树 区间替换 和区间求和 模板题 只不过不需要查询 题里只问了全部区间的和,所以seg[ ...
- HDU 1556 Color the ball(线段树区间更新)
Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
- (简单) HDU 1698 Just a Hook , 线段树+区间更新。
Description: In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of ...
- HDU 1698 Just a Hook(线段树区间更新查询)
描述 In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes ...
- hdu 1556 Color the ball(线段树区间维护+单点求值)
传送门:Color the ball Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/3276 ...
随机推荐
- Windows下虚拟机Linux(CentOS8)扩容设置 - 磁盘扩容中的坑和解决方法
摘要:[原创]转载请注明作者Johnthegreat和本文链接 由于虚拟机空间不足,为了避免重装虚拟机,做了一次无损扩容. 过程中的报错如下: [root@localhost ~]# pvcrea ...
- 温故知新-java虚拟机
文章目录 java虚拟机是什么? jvm的体系结构 第一个类加载子系统 类的生命周期 加载器分类 类加载机制 第二个运行时数据区(内存结构) GC算法和收集器 如何判断对象可以被回收? 如何判断一个常 ...
- Python数据分析软件包介绍
Python数据分析主要软件包: 1.python -m pip install numpy 2.python -m pip install pandas 3.python -m pip instal ...
- SuperSlide之属性targetCell介绍
禁用页面菜单js代码: <script type="text/javascript"> document.oncontextmenu=function(){ retur ...
- css3动画特效代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- IDEA之maven配置详解
这两天被maven配置搞得焦头烂额,前后忙活了三天才彻底搞定. 下面我总结一下配置的步骤. 步骤 1. 首先去maven官网去下载maven,http://maven.apache.org/ 这里教大 ...
- winXP vc6行号显示插件-VC6LineNumberAddin方法-可用-无需注册
1.VC6LineNumberAddin 修改日期是2008.6.3可用,其它需要注册码 http://codefish.googlecode.com/files/VC%E6%98%BE%E7%A4% ...
- PHP丨PHP基础知识之PHP基础入门——函数「理论篇」
前两天讲过PHP基础知识的判断条件和流程控制,今天来讲讲PHP基础知识之PHP基础入门--函数! 一.函数的声明与使用 1.函数名是标识符之一,只能有数字字母下划线,开头不能是数字. 函数名的命名,须 ...
- 一个老牌程序员说:做Java开发,怎么可以不会这 20 种类库和 API
- Domain Adaptive Faster R-CNN:经典域自适应目标检测算法,解决现实中痛点,代码开源 | CVPR2018
论文从理论的角度出发,对目标检测的域自适应问题进行了深入的研究,基于H-divergence的对抗训练提出了DA Faster R-CNN,从图片级和实例级两种角度进行域对齐,并且加入一致性正则化来学 ...