Codeforces 484 E. Sign on Fence
[传送门]
题意就是给一排围栏,每个围栏都有一个高度,查询区间$\left[l, r\right]$之间长度为$w$的子区间的最小高度的最大值。
首先,这个最大值肯定是这个区间里的围栏的某个高度,如果是一个未出现过的高度,显然能有更高的高度满足条件。
那么就可以考虑在离散化后的高度数组里二分答案,然后check一下这个区间里是否有连续$w$个围栏的高度大于等于这个答案。
因为答案肯定是出现过的高度这个性质,那么可以考虑以高度建一棵可持久化线段树,先将高度数组离散化排好序,第$i$个版本的线段树代表的是下标位置的围栏的高度是否大于等于$h_i$,然后保存区间前缀最长连续1、后缀最长连续1、区间最长连续1。第$i$个版本由第$i-1$个版本再加上几个单点修改得来。
查询就保存区间最长前缀及最长后缀进行合并,合并过程更新一下答案。
说起来容易想起来难。我菜爆了。
#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + ;
int n, a[N], h[N], root[N], tol, ans;
vector<int> G[N]; struct Seg {
struct Tree {
int lp, rp, len, pre, suf, mx;
} tree[N * ];
inline void pushup(int p) {
tree[p].pre = tree[tree[p].lp].pre + (tree[tree[p].lp].pre == tree[tree[p].lp].len ? tree[tree[p].rp].pre : );
tree[p].suf = tree[tree[p].rp].suf + (tree[tree[p].rp].suf == tree[tree[p].rp].len ? tree[tree[p].lp].suf : );
tree[p].mx = max(tree[tree[p].lp].suf + tree[tree[p].rp].pre, max(tree[tree[p].lp].mx, tree[tree[p].rp].mx));
}
void build(int &p, int l, int r) {
p = ++tol;
tree[p].len = tree[p].pre = tree[p].suf = tree[p].mx = r - l + ;
if (l == r) return;
int mid = l + r >> ;
build(tree[p].lp, l, mid);
build(tree[p].rp, mid + , r);
}
void update(int &p, int q, int l, int r, int pos) {
tree[p = ++tol] = tree[q];
if (l == r) {
tree[p].pre = tree[p].suf = tree[p].mx = ;
return;
}
int mid = l + r >> ;
if (pos <= mid) update(tree[p].lp, tree[q].lp, l, mid, pos);
else update(tree[p].rp, tree[q].rp, mid + , r, pos);
pushup(p);
}
pair<int, int> query(int p, int l, int r, int x, int y) {
if (x <= l && y >= r) {
ans = max(ans, tree[p].mx);
return pair<int, int>(tree[p].pre, tree[p].suf);
}
int mid = l + r >> ;
pair<int, int> L(, ), R(, );
if (x <= mid) L = query(tree[p].lp, l, mid, x, y);
if (y > mid) R = query(tree[p].rp, mid + , r, x, y);
ans = max(ans, L.second + R.first);
return pair<int, int>(L.first + (L.first == tree[tree[p].lp].len ? R.first : ),
R.second + (R.second == tree[tree[p].rp].len ? L.second : ));
}
} seg; int main() {
scanf("%d", &n);
for (int i = ; i <= n; i++)
scanf("%d", &a[i]), h[i] = a[i];
sort(h + , h + + n);
int cnt = unique(h + , h + + n) - h - ;
for (int i = ; i <= n; i++) {
int pos = lower_bound(h + , h + + cnt, a[i]) - h;
G[pos].push_back(i);
}
seg.build(root[], , n);
for (int i = ; i <= cnt; i++) {
root[i] = root[i - ];
for (int x: G[i - ]) {
seg.update(root[i], root[i], , n, x);
}
}
int q;
scanf("%d", &q);
while (q--) {
int x, y, w;
scanf("%d%d%d", &x, &y, &w);
int res = ;
int l = , r = cnt;
while (l <= r) {
int mid = (l + r + ) >> ;
ans = ;
seg.query(root[mid], , n, x, y);
if (ans >= w) l = mid + , res = mid;
else r = mid - ;
}
printf("%d\n", h[res]);
}
return ;
}
Codeforces 484 E. Sign on Fence的更多相关文章
- CF&&CC百套计划4 Codeforces Round #276 (Div. 1) E. Sign on Fence
http://codeforces.com/contest/484/problem/E 题意: 给出n个数,查询最大的在区间[l,r]内,长为w的子区间的最小值 第i棵线段树表示>=i的数 维护 ...
- Codeforces 484E Sign on Fence(是持久的段树+二分法)
题目链接:Codeforces 484E Sign on Fence 题目大意:给定给一个序列,每一个位置有一个值,表示高度,如今有若干查询,每次查询l,r,w,表示在区间l,r中, 连续最长长度大于 ...
- Codeforces Round #276 (Div. 1) E. Sign on Fence 二分+主席树
E. Sign on Fence Bizon the Champion has recently finished painting his wood fence. The fence consi ...
- AC日记——Sign on Fence Codeforces 484e
E. Sign on Fence time limit per test 4 seconds memory limit per test 256 megabytes input standard in ...
- CF 484E - Sign on Fence
E. Sign on Fence time limit per test 4 seconds memory limit per test 256 megabytes input standard in ...
- 【CF484E】Sign on Fence(主席树)
[CF484E]Sign on Fence(主席树) 题面 懒得贴CF了,你们自己都找得到 洛谷 题解 这不就是[TJOI&HEOI 排序]那题的套路吗... 二分一个答案,把大于答案的都变成 ...
- CF484E Sign on Fence && [国家集训队]middle
CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 1 ...
- Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)
链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...
- Sign on Fence CodeForces - 484E
http://codeforces.com/problemset/problem/484/E 题意: 给定一个长度为n的数列,有m次询问,询问形如l r k 要你在区间[l,r]内选一个长度为k的区间 ...
随机推荐
- Remote Desktop突然不能用了 “This could be due to CredSSP encryption oracle remediation”
一段时间没有用RDP去连远程的Windows主机,某一天突然发现用不了了. 错误信息如下: An authentication error has occurred. The function req ...
- c++中如何判断sqlite表是否存在
在项目中遇到需要判断sqlite数据库中某个表是否存在,上网搜索一些资料后,解决了问题,如下: 首先,在每个sqlite数据库中,都有一个名为sqlite_master的表,它定义了数据库的模式,它的 ...
- LaTeX 小试牛刀
跟大家分享一下正式第一次使用 LaTex 的经验,之前数学建模的时候一直想用,但没有找到合适的软件.前段时间,实验室老师让我帮忙套个 IEEE ACCESS 的模板. 尝试过 TexPad,的确 UI ...
- 300iq Contest 1 简要题解
300iq Contest 1 简要题解 咕咕咕 codeforces A. Angle Beats description 有一张\(n\times m\)的方阵,每个位置上标有*,+,.中的一种. ...
- Java学习:运算符的使用与注意事项
运算符的使用与注意事项 四则运算当中的加号“+”有常见的三种用法: 对于数值来,那就是加法. 对于字符char类型来说,在计算之前,char会被提升成为int,然后再计算.char类型字符,和int类 ...
- golang学习笔记--函数和方法
在go中,函数类型是一等类型,这意味着可以吧函数当做一个值来传递和使用. func divide(dividend int,divisor int)(int,error){ //省略部分代码 } 参数 ...
- qbittorrent搜索插件合集
qbittorrent搜索 qbittorrent搜索一个很有特色的功能: 这里收集整理了一些公开网站的插件(Plugins for Public sites),并连 源py文件一起分享. qbitt ...
- css 光标
<style> div{width:100;height:50;float:left;border:1px solid red;margin:1px;} </style> &l ...
- Echarts X轴多项百分比的展示
app.title = '堆叠柱状图'; option = { tooltip : { trigger: 'axis', axisPointer : { // 坐标轴指示器,坐标轴触发有效 type ...
- WPF调用C++生成的dll文件(示例)
注:笔者使用的VS版本为2019.1.打开VS2019,选择文件 -> 新建 -> 项目 2.选择项目 新建项目时选择C++“控制台应用”语言:C++平台:Windows项目类型:空项目 ...