「CF484E」Sign on Fence「整体二分」「线段树」
题意
给定一个长度为\(n\)的正整数序列,第\(i\)个数为\(h_i\),\(m\)个询问,每次询问\((l, r, w)\),为\([l, r]\)所有长度为\(w\)的子区间最小值的最大值。(类似于一类特殊的直方图最大子矩形问题)
\(1 \leq n, m \leq 10^5\)
题解
我们考虑二分答案,这样\(n\)个数变成\(01\),若\(h_i\geq mid\)则为\(0\),否则为\(1\)
每次就相当于查询存不存在长度为\(w\)的连续\(1\)。用线段树维护。
这有个问题,\([l, r]\)分成\([l, mid - 1]\)和\([mid, r]\)的时候,左区间统计不到右区间的贡献。那我们就递归左区间之前不清空线段树,等到递归右区间的时候再清空。
时间复杂度两个log
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 2e5 + 10;
struct opt { int l, r, k, id; } q[N], qL[N], qR[N];
int n, m, h[N], ans[N];
struct node { int res, l, r, len; } t[N << 2];
node operator + (const node &a, const node &b) {
node ans; ans.len = a.len + b.len;
ans.l = a.l == a.len ? a.l + b.l : a.l;
ans.r = b.r == b.len ? b.r + a.r : b.r;
ans.res = max(max(a.res, b.res), a.r + b.l);
return ans;
}
void build(int u, int l, int r) {
if(l == r) { t[u] = (node) {0, 0, 0, 1}; return ; }
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
t[u] = t[u << 1] + t[u << 1 | 1];
}
void ins(int u, int l, int r, int x, int y) {
if(l == r) { t[u] = (node) {y, y, y, 1}; return ; }
int mid = (l + r) >> 1;
if(x <= mid) ins(u << 1, l, mid, x, y);
else ins(u << 1 | 1, mid + 1, r, x, y);
t[u] = t[u << 1] + t[u << 1 | 1];
}
node qry(int u, int l, int r, int ql, int qr) {
if(l == ql && r == qr) return t[u];
int mid = (l + r) >> 1;
if(qr <= mid) return qry(u << 1, l, mid, ql, qr);
if(ql > mid) return qry(u << 1 | 1, mid + 1, r, ql, qr);
return qry(u << 1, l, mid, ql, mid) + qry(u << 1 | 1, mid + 1, r, mid + 1, qr);
}
void solve(int ql, int qr, int l, int r) {
if(ql > qr || l > r) return ;
if(l == r) {
for(int i = ql; i <= qr; i ++) ans[q[i].id] = l;
return ;
}
// printf("[%d, %d] & [%d, %d]\n", ql, qr, l, r);
int mid = (l + r + 1) >> 1, nl = 0, nr = 0;
for(int i = ql; i <= qr; i ++) {
if(!q[i].id) {
if(q[i].k >= mid) ins(1, 1, n, q[i].l, 1), qR[nr ++] = q[i];
else qL[nl ++] = q[i];
} else {
int res = qry(1, 1, n, q[i].l, q[i].r).res;
if(res >= q[i].k) qR[nr ++] = q[i];
else qL[nl ++] = q[i];
}
}
for(int i = 0; i < nl; i ++) q[ql + i] = qL[i];
for(int i = 0; i < nr; i ++) q[ql + nl + i] = qR[i];
solve(ql, ql + nl - 1, l, mid - 1);
for(int i = ql + nl; i <= qr; i ++) if(!q[i].id && q[i].k >= mid) ins(1, 1, n, q[i].l, 0);
solve(ql + nl, qr, mid, r);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", h + i), q[i] = (opt) {i, 0, h[i], 0};
int l = *min_element(h + 1, h + n + 1);
int r = *max_element(h + 1, h + n + 1);
scanf("%d", &m);
for(int i = n + 1; i <= n + m; i ++) {
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k); q[i].id = i - n;
}
build(1, 1, n); solve(1, n + m, l, r);
for(int i = 1; i <= m; i ++) printf("%d\n", ans[i]);
return 0;
}
「CF484E」Sign on Fence「整体二分」「线段树」的更多相关文章
- (困难) CF 484E Sign on Fence,整体二分+线段树
Bizon the Champion has recently finished painting his wood fence. The fence consists of a sequence o ...
- 【XSY2720】区间第k小 整体二分 可持久化线段树
题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...
- 2019.01.14 bzoj5343: [Ctsc2018]混合果汁(整体二分+权值线段树)
传送门 整体二分好题. 题意简述:nnn种果汁,每种有三个属性:美味度,单位体积价格,购买体积上限. 现在有mmm个询问,每次问能否混合出总体积大于某个值,总价格小于某个值的果汁,如果能,求所有方案中 ...
- P5163 WD与地图(整体二分+权值线段树)
传送门 细节要人命.jpg 这题思路太新奇了--首先不难发现可以倒着做变成加边,但是它还需要我们资瓷加边的同时维护强连通分量.显然加边之后暴力跑是不行的 然后有一个想法,对于一条边\((u,v)\), ...
- 【CF484E】Sign on Fence(主席树)
[CF484E]Sign on Fence(主席树) 题面 懒得贴CF了,你们自己都找得到 洛谷 题解 这不就是[TJOI&HEOI 排序]那题的套路吗... 二分一个答案,把大于答案的都变成 ...
- 「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数
「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数 题面描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数, ...
- 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]
题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...
- [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组
Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...
- 「CF319E」Ping-Pong「线段树」「并查集」
题意 规定区间\((a,b)\)到区间\((c,d)\)有边当且仅当\(c<a<d\)或\(c<b<d\). 起初区间集合为空.有\(n\)(\(n\leq 10^5\))次操 ...
随机推荐
- 跟我一起学编程—《Scratch编程》第21课:打地鼠
能够熟练创建并使用变量 能够熟练使用“广播”和侦测指令 能够熟练绘制角色和背景造型 能够熟练使用循环.选择等程序指令 任务描述: 绘制有6个地洞的背景:绘制锤子的两个造型:绘制地鼠的造型. 游戏开始后 ...
- mysql5.7主主(双主)复制
在server1上操作 vi /etc/my.cnf 修改或添加下面这几行: server-id=1 log-bin=mysql-bin # 启用二进制日志 auto-increment-increm ...
- (五)Hibernate的增删改查操作(2)
接上一章节 HQL的预编译语句 HIbernate中的预编译与Spring的预编译的处理差不多. 1:使用标准的? 2:使用命名参数 2.1:使用名称逐个设置. 2.2:使用Map(k ...
- C# explicit interface implementation(显式接口实现)
C# explicit interface implementation 某个类要实现两个包含相同方法名的接口, 应该如何实现这两个方法? namespace ExplicitInterfaceImp ...
- VBA if...else语句
一个if语句由一个布尔表达式和一个或多个语句组成.如果条件评估为True,则执行if条件下的语句.如果条件评估为False,则执行else部分块下的语句. 语法 以下是VBScript中的if els ...
- \lib\cmsis\stm32f10x.h(298): error: #67: expected a "}"
首先介绍一下csdn屏蔽广告 这个至关重要,请参考 https://blog.csdn.net/qq_40881680/article/details/82226562 更新KEIL5以后,原KEIL ...
- C++ 获取对象类型
在入门C++过程中,我们经常会遇到无法判断对象类型的情况. 头文件( VS编译器 ) #include <typeinfo> typeid(对象).name(); 例子: , &b ...
- 【leetcode】575. Distribute Candies
原题 Given an integer array with even length, where different numbers in this array represent differen ...
- Python学习记录8-继承2
继承 单继承和多继承 单继承:每个类只能继承一个类 多继承:每个类允许继承多个类 >>> class A(): pass >>> class B(A): pass ...
- mesos-master启动失败,报错Failed to load unknown flag 'quorum.rpmsave'
[现象] mesos启动失败,查看mesos状态报错: [root@hps102 ~]# systemctl status mesos-master ● mesos-master.service - ...