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 ...
随机推荐
- java代码(14) --Java8函数式接口
Java8函数式接口 之前有关JDK8的Lambda表达式 Java代码(1)--Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁 一.概 ...
- 【JavaScript】原生js实现:强制保留2位小数(由于toFixed()报错)
function decimal(x) { var f = parseFloat(x); if (isNaN(f)) { alert("请输入数字!"); return; } va ...
- 痞子衡嵌入式:降低刷新率是定位LCD花屏显示问题的第一大法(i.MXRT1170, 1280x480 LVDS)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170上LCD花屏显示问题的分析解决经验. 痞子衡最近这段时间在参与一个基于i.MXRT1170的大项目(先保个密),需要 ...
- 一个static和面试官扯了一个小时,舌战加强版
一:背景 1. 讲故事 最近也是奇怪,在社区里看到好几篇文章聊static 的玩法以及怎么拿这个和面试官扯半个小时,有点意思,点进去看都是java版的,这就没意思了,怎么也得有一篇和面试官扯C# 中的 ...
- char、short、int、unigned int 之间的类型转换
标准数据类型之间会进行 隐式类型的安全转换 转换规则如下: char→int→unsigned int →long→unsigned long→float→double ↓ sho ...
- javascript 面向对象学习(一)——构造函数
最近在学习设计模式,找了很多资料也没有看懂,看到怀疑智商,怀疑人生,思来想去还是把锅甩到基础不够扎实上.虽然原型继承.闭包.构造函数也都有学习过,但理解得不够透彻,影响到后续提高.这次重新开始学习,一 ...
- [xDebug] PhpStorm Xdebug远程调试环境搭建
对于简单的工程,直接print_r();exit()已经足够,但是对于大型项目有时就有点力不从心.. 1,环境介绍 本地:windows10(192.168..)+ phpstorm8远程:Cento ...
- Python实现DPABI当中“DICOM Sorted”功能
1. 前言 在对DICOM数据预处理之前很重要的一步是将扫描得到的文件按照不同的扫描序列区分开来.DPABI和PANDA工具包中已经提供了相应的功能模块.但由于是集成的模块,不容易及逆行扩展和调整.这 ...
- 【JMeter_03】JMeter GUI操作界面介绍
JMeter主界面主要分为 标题栏.菜单栏.工具栏.测试计划树形目录.内容展示区 标题栏:主要展示JMeter的程序版本.当前脚本的名称.脚本的储存路径 菜单栏:程序基本上所有功能的所属分类目录,基本 ...
- 【Flutter实战】六大布局组件及半圆菜单案例
老孟导读:Flutter中布局组件有水平 / 垂直布局组件( Row 和 Column ).叠加布局组件( Stack 和 IndexedStack ).流式布局组件( Wrap )和 自定义布局组件 ...