Codeforces 840D [主席树]

来源:互联网 发布:淘宝代理货源平台 编辑:程序博客网 时间:2024/05/22 20:22

Description

q次询问,每次询问区间[l,r]中出现次数大于(rl+1)k的数的最小值。

Solution

跟PBS和gjghfd大神打cf的vp。
这个题跟以前一道区间众数很像,发现k5只要查询区间第(rl+1)ik(1ik)大的数,并判一下是否出现了这么多次即可。
用主席数维护。。
脑抽多打了一个东西。。

#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;}
原创粉丝点击