Description
q
次询问,每次询问区间
Solution
跟PBS和gjghfd大神打cf的vp。
这个题跟以前一道区间众数很像,发现
k≤5
只要查询区间第
⌊(r−l+1)∗ik⌋
(1≤i≤k)
大的数,并判一下是否出现了这么多次即可。
用主席数维护。。
脑抽多打了一个东西。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
inline void read(int &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
const int N = 303030;
const int INF = 1 << 30;
int rt[N], ls[N * 20], rs[N * 20], size[N * 20], a[N];
int n, q, l, r, k, Tcnt, ans, p, num;
inline int Min(int a, int b) {
return a < b ? a : b;
}
inline void Insert(int &o, int l, int r, int pos) {
ls[++Tcnt] = ls[o]; rs[Tcnt] = rs[o];
size[Tcnt] = size[o] + 1; o = Tcnt;
if (l == r) return;
int mid = (l + r) >> 1;
if (pos <= mid) Insert(ls[o], l, mid, pos);
else Insert(rs[o], mid + 1, r, pos);
}
inline int Kth(int x, int y, int k) {
x = rt[x]; y = rt[y];
int l = 1, r = n, mid;
while (l != r) {
mid = (l + r) >> 1;
if (size[ls[y]] - size[ls[x]] >= k) {
x = ls[x]; y = ls[y];
r = mid;
} else {
k -= size[ls[y]] - size[ls[x]];
x = rs[x]; y = rs[y];
l = mid + 1;
}
}
return l;
}
inline int Query(int x, int y, int p) {
x = rt[x]; y = rt[y];
int l = 1, r = n, mid;
while (l != r) {
mid = (l + r) >> 1;
if (p <= mid) {
x = ls[x]; y = ls[y];
r = mid;
} else {
x = rs[x]; y = rs[y];
l = mid + 1;
}
}
return size[y] - size[x];
} // 多打的东西。。
int main(void) {
freopen("1.in", "r", stdin);
read(n); read(q);
for (int i = 1; i <= n; i++) {
read(a[i]); rt[i] = rt[i - 1];
Insert(rt[i], 1, n, a[i]);
}
while (q--) {
read(l); read(r); read(k);
ans = INF;
for (int i = 1; i <= k; i++) {
p = (r - l + 1) * i / k;
if (Query(l - 1, r, num = Kth(l - 1, r, p)) > (r - l + 1) / k)
ans = Min(ans, num);
}
if (ans == INF) ans = -1;
printf("%d\n", ans);
}
return 0;
}