[传送门]

题意就是给一排围栏,每个围栏都有一个高度,查询区间$\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的更多相关文章

  1. 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的数 维护 ...

  2. Codeforces 484E Sign on Fence(是持久的段树+二分法)

    题目链接:Codeforces 484E Sign on Fence 题目大意:给定给一个序列,每一个位置有一个值,表示高度,如今有若干查询,每次查询l,r,w,表示在区间l,r中, 连续最长长度大于 ...

  3. 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 ...

  4. 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 ...

  5. CF 484E - Sign on Fence

    E. Sign on Fence time limit per test 4 seconds memory limit per test 256 megabytes input standard in ...

  6. 【CF484E】Sign on Fence(主席树)

    [CF484E]Sign on Fence(主席树) 题面 懒得贴CF了,你们自己都找得到 洛谷 题解 这不就是[TJOI&HEOI 排序]那题的套路吗... 二分一个答案,把大于答案的都变成 ...

  7. CF484E Sign on Fence && [国家集训队]middle

    CF484E Sign on Fence #include<bits/stdc++.h> #define RG register #define IL inline #define _ 1 ...

  8. Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)

    链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...

  9. Sign on Fence CodeForces - 484E

    http://codeforces.com/problemset/problem/484/E 题意: 给定一个长度为n的数列,有m次询问,询问形如l r k 要你在区间[l,r]内选一个长度为k的区间 ...

随机推荐

  1. jmeter 生成不重复的手机号

    String account = "${__time(yyyyMMdd,)}"+UUID.randomUUID().toString().split("-")[ ...

  2. git实战中遇到git@github.com: Permission denied (publickey).的问题

    一.问题我们在使用git的时候会建立一个私钥和一个公钥来完成彼此的通讯,因此如何使用给一个指令建立一个秘钥至关重要.但是我在实践的过程中出现了git@github.com: Permission de ...

  3. MOOC 数据库笔记(五):关系演算

    关系演算 概述 (这部分的内容大多与离散数学有关,我没有相关基础,所以现在只是简单看一下) 关系演算是以数理逻辑中的谓词演算为基础的. 关系演算是描述关系运算的另一种思维方式. SQL语言是继承了关系 ...

  4. framework7 下拉刷新、无限滚动

    下拉刷新: html: <div class="page-content ptr-content"> <%--下拉刷新图标--%> <div clas ...

  5. asp.net core 系列之允许跨域访问2之测试跨域(Enable Cross-Origin Requests:CORS)

    这一节主要讲如何测试跨域问题 你可以直接在官网下载示例代码,也可以自己写,我这里直接使用官网样例进行演示 样例代码下载: Cors 一.提供服务方,这里使用的是API 1.创建一个API项目.或者直接 ...

  6. C# 调用JS Eval,高效率

    /// <summary> /// 动态计算表达式 /// </summary> class JSCaller { /// <summary> /// 动态计算表达 ...

  7. JavaScript---Bom树的操作,内置方法和内置对象(window对象,location对象,navigator对象,history对象,screen对象)

    JavaScript---Bom树的操作,内置方法和内置对象(window对象,location对象,navigator对象,history对象,screen对象) 一丶什么是BOM ​      B ...

  8. 【转】用Python做股市量化策略投资数据分析

    金融量化分析介绍     本文摘要; 金融量化分析介绍 1.什么是金融量化分析 2.金融量化分析可以干什么 3.为什么将python运用于金融 4.常用库简介 1.什么是金融量化分析 从标题中我们可以 ...

  9. 纯css无js实现点击事件

    <input id="A" type="checkbox"><label for="A"> <span cla ...

  10. JavaScript 之 RegExp 对象

    RegExp 正则表达式对象 一.正则表达式 正则表达式:定义字符串的组成规则. 1.单个字符:[ ] 如:[a].[ab].[a-zA-Z0-9] 特殊符号代表特殊含义的单个字符: \d:单个数字字 ...