题目大意:一个长度为$n$的数列,$m$次询问。每次询问$l;r;k$,表示在区间$[l,r]$内选一个长度为$k$的区间,求区间最小数的最大值
题解:常见操作,开一棵主席树,比这一位大的就赋成$1$,否则为$0$,维护前缀$1$的个数,后缀$1$的个数和区间最长$1$的个数,二分答案判断一下就行了
卡点:无
C++ Code:
#include <cstdio> #include <algorithm> #define maxn 100010 #define N maxn * 20 int n, m; int v[maxn], rnk[maxn]; inline int min(int a, int b) {return a < b ? a : b;} inline int max(int a, int b) {return a > b ? a : b;} inline bool cmp(int a, int b) {return v[a] > v[b];} inline bool cmp1(int a, int b) {return a > b;} namespace Segment_Tree { struct node { int ml, mr, len, sz; node() {ml = mr = len = sz = 0;} node(int x) {ml = mr = len = sz = x;} inline node operator + (node rhs) const { node res; res.len = max(len, rhs.len); res.ml = ml + (sz == ml ? rhs.ml : 0); res.mr = rhs.mr + (rhs.sz == rhs.mr ? mr : 0); res.len = max(res.len, mr + rhs.ml); res.sz = sz + rhs.sz; return res; } } V[N]; int root[maxn], lc[N], rc[N], idx; void build(int &rt, int l, int r) { rt = ++idx; if (l == r) { V[rt].sz = 1; return ; } int mid = l + r >> 1; build(lc[rt], l, mid); build(rc[rt], mid + 1, r); V[rt] = V[lc[rt]] + V[rc[rt]]; } int p; void ADD(int &rt, int l, int r) { lc[++idx] = lc[rt], rc[idx] = rc[rt], V[idx] = V[rt]; rt = idx; if (l == r) { V[rt] = node(1); return ; } int mid = l + r >> 1; if (p <= mid) ADD(lc[rt], l, mid); else ADD(rc[rt], mid + 1, r); V[rt] = V[lc[rt]] + V[rc[rt]]; } inline void add(int &rt, int P) { p = P; ADD(rt, 1, n); } int L, R; node ASK(int rt, int l, int r) { if (L <= l && R >= r) return V[rt]; int mid = l + r >> 1; node ans; if (L <= mid) ans = ASK(lc[rt], l, mid); if (R > mid) ans = ans + ASK(rc[rt], mid + 1, r); return ans; } inline node ask(int rt, int ll, int rr) { L = ll, R = rr; return ASK(rt, 1, n); } } using Segment_Tree::add; using Segment_Tree::ask; using Segment_Tree::root; int LL, RR, KK; inline bool check(int mid) { return ask(root[mid], LL, RR).len >= KK; } inline int solve() { int l = 1, r = n, ans = n; while (l <= r) { int mid = l + r >> 1; if (check(mid)) { ans = mid; r = mid - 1; } else l = mid + 1; } return v[ans]; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", v + i), rnk[i] = i; std::sort(rnk + 1, rnk + n + 1, cmp); std::sort(v + 1, v + n + 1, cmp1); Segment_Tree::build(root[0], 1, n); for (int i = 1; i <= n; i++) { root[i] = root[i - 1]; add(root[i], rnk[i]); } scanf("%d", &m); while (m --> 0) { scanf("%d%d%d", &LL, &RR, &KK); printf("%d ", solve()); } return 0; }