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 ...
随机推荐
- 基于springcloud gateway + nacos实现灰度发布(reactive版)
什么是灰度发布? 灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式.在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B ...
- vue2.0 + Element UI + axios实现表格分页
注:本文分页组件用原生 html + css 实现,element-ui里有专门的分页组件可以不用自己写,详情见另一篇博客:https://www.cnblogs.com/zdd2017/p/1115 ...
- Win10下Tensorflow的安装
Win10下Tensorflow的安装 1. Tensorflow简介 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张 ...
- @loj - 2106@ 「JLOI2015」有意义的字符串
目录 @description@ @solution@ @accepted code@ @details@ @description@ B 君有两个好朋友,他们叫宁宁和冉冉.有一天,冉冉遇到了一个有趣 ...
- Seafile的配置
如果部署在apache或nginx后面,就是访问默认80或443.反向代理会帮你转到8000和8082上. 我使用443,我在路由器上设定了转发,比如 对外网12323这个端口会转到内网地址443上 ...
- MyISAM和InnoDB的差异
转载:https://www.cnblogs.com/xc-chejj/p/11245034.html MyISAM是默认表类型,基于ISAM(Indexed Sequential Access Me ...
- startActivityForResult调用另外一个Activity获取返回结果
startActivityForResult(intent,requestCode)可以调用另外一个Activity,并返回结果. 换头像案例 activity_main.xml <?xml v ...
- c++ UDP套接字客服端代码示范
c++ UDP套接字客服端代码示范 #include<winsock2.h> //包含头文件 #include<stdio.h> #include<windows.h&g ...
- JavaWeb网上图书商城完整项目--26.注册页面之验证码换一张实现
我们现在要实现点击换一张的时候实现验证码的修改 我们首先在html添加函数点击事件: <%@ page language="java" contentType="t ...
- 5、struct2的获得jsp参数的第三种方式
在前面已经讲解了通过在action中直接通过jsp的参数和ModelDiver的方式获得浏览器传递的参数,下面我们介绍第三种方式,也是在项目开发中推荐的方式 action不需要在实现ModelDriv ...