题意
给定一个长度为n的数列,有m次询问,询问形如l r k
要你在区间[l,r]内选一个长度为k的区间,求区间最小数的最大值
Sol
二分答案
怎么判定,每种数字开一棵线段树
某个位置上的数大于等于它为1
那么就是求区间最大的1的序列长度大于k
二分的最优答案一定在这个区间内,否则不优
排序后就是用主席树优化空间
之前\(build\)一下,因为区间有长度不好赋值
# include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(1e5 + 5); const int __(2e6 + 5); IL int Input(){ RG int x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z; } int n, m, tot, rt[_], a[_], id[_], ls[__], rs[__], o[_], len; struct Data{ int maxl, maxr, maxn, len; IL void Init(){ maxl = maxr = maxn = len = 0; } } T[__], Ans; IL int Cmp(RG int x, RG int y){ return a[x] < a[y]; } IL Data Merge(RG Data A, RG Data B){ RG Data ret; ret.maxl = A.maxl, ret.maxr = B.maxr, ret.len = A.len + B.len; ret.maxn = max(A.maxr + B.maxl, max(A.maxn, B.maxn)); if(A.maxl == A.len) ret.maxl = A.len + B.maxl; if(B.maxr == B.len) ret.maxr = B.len + A.maxr; return ret; } IL void Modify(RG int &x, RG int l, RG int r, RG int p){ ls[++tot] = ls[x], rs[tot] = rs[x], T[tot] = T[x], x = tot; if(l == r){ T[x].maxl = T[x].maxr = T[x].maxn = 1; return; } RG int mid = (l + r) >> 1; if(p <= mid) Modify(ls[x], l, mid, p); else Modify(rs[x], mid + 1, r, p); T[x] = Merge(T[ls[x]], T[rs[x]]); } IL void Query(RG int x, RG int l, RG int r, RG int L, RG int R){ if(L <= l && R >= r){ Ans = Merge(Ans, T[x]); return; } RG int mid = (l + r) >> 1; if(L <= mid) Query(ls[x], l, mid, L, R); if(R > mid) Query(rs[x], mid + 1, r, L, R); } IL void Build(RG int &x, RG int l, RG int r){ T[x = ++tot].len = r - l + 1; if(l == r) return; RG int mid = (l + r) >> 1; Build(ls[x], l, mid), Build(rs[x], mid + 1, r); } int main(RG int argc, RG char* argv[]){ n = Input(); for(RG int i = 1; i <= n; ++i) id[i] = i, o[i] = a[i] = Input(); sort(id + 1, id + n + 1, Cmp), sort(o + 1, o + n + 1); len = unique(o + 1, o + n + 1) - o - 1; Build(rt[len + 1], 1, n); for(RG int i = len, j = n; i; --i){ rt[i] = rt[i + 1]; for(; j && a[id[j]] == o[i]; --j) Modify(rt[i], 1, n, id[j]); } m = Input(); for(RG int i = 1; i <= m; ++i){ RG int l = Input(), r = Input(), k = Input(); RG int L = 1, R = len, ans = 0; while(L <= R){ RG int mid = (L + R) >> 1; Ans.Init(); Query(rt[mid], 1, n, l, r); if(Ans.maxn >= k) ans = mid, L = mid + 1; else R = mid - 1; } printf("%d\n", o[ans]); } return 0; }
来源:https://www.cnblogs.com/cjoieryl/p/8489731.html