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的区间 ...
随机推荐
- Matlab 整数线性规划问题模型代码
整数线性规划问题的基本内容 整数线性规划解决的是自变量在一定的线性约束条件下,使得线性目标函数求得最大值或者最小值的问题.其中自变量只能取整数.特别地,当自变量只能取0或者1时,称之为 0-1 整数规 ...
- 软件——解决Modelsim10.1d窗口不停弹出问题(一直弹窗)
博主在编写Verilog HDL时需要用到Modelsim,于是博主便安装了Modelsim10.1d,然后兴高采烈打开准备跑仿真时,打开软件发现Modelsim10.1d的各种窗口在不停弹出,终止进 ...
- tornado之websoket
继承WebSoketHandler def open(self): # 当一个WebSoket连接建立之后被调用 def on_message(self, message): # 当客户端发送一个消息 ...
- python+requests+unittest 接口ddt测试
以数据驱动的形式,将用例维护在py文件中 源码分析: 变量定义 publicParameters.py """ 公共参数 , 按照各公司实情,自行编写 "&qu ...
- 重温拉格朗日乘子法和KKT条件
在求取有约束条件的优化问题时,拉格朗日乘子法(Lagrange Multiplier) 和KKT条件是非常重要的两个求取方法,对于等式约束的优化问题,可以应用拉格朗日乘子法去求取最优值:如果含有不等式 ...
- drf之视图类与路由
视图 Django REST framwork 提供的视图的主要作用: 控制序列化器的执行(检验.保存.转换数据) 控制数据库查询的执行 2个视图基类 APIView rest_framework.v ...
- java.net.URLEncoder对中文的编码和解码
// java.net.URLEncoder对中文的编码和解码String str = URLEncoder.encode("测试字符串", "utf-8"); ...
- English--定语从句
English|定语从句 从介绍从句开始,英语的句子已经开始逐渐复杂了!做好心理准备,三大从句介绍完毕,会介绍分词短语.废话不多说,直接开始干! 前言 目前所有的文章思想格式都是:知识+情感. 知识: ...
- BUAA-OO-2019 第二单元总结
第五次作业 本次作业,需要完成的任务为单部多线程傻瓜调度(FAFS)电梯的模拟. 设计策略 先来先服务的单电梯是一个标准的"生产者-消费者"模型.虽然在本次作业中调度器似乎是不必要 ...
- Microsoft SQL Server数据库语法
目录 关于数据库的语法: 1.创建数据库 create database 数据库名on primary(主文件属性(name,filename,size等)) -用逗号隔开次要主要文件和次要文件( ...