spoj K-th Number (classic! 区间静态第k大)

来源:互联网 发布:spring源码视频百度云 编辑:程序博客网 时间:2024/05/18 03:20

这道题的 comment 里有人说
题目链接

Beautiful problem. There exists solution which run in O(log^3 N), O(log^2 N), and O(log N) per query. Explore them and learn something new!

我学到的第一种应该是最大的那种, 就是构造一个线段树, 其中每个节点都是排序后的对应区间上的数。然后通过二分求第k大
这种只能处理静态。。

const int N = 100005;int n, m, ai[N];vector<int> tree[N*4], nodes;#define lc o<<1#define rc o<<1|1void build(int o, int l, int r) {    if ( l == r ) {        int x;        scanf("%d", &x);        tree[o].push_back(x);    } else {        int m = (l + r) >> 1;        build(lc, l, m);        build(rc, m + 1, r);        tree[o].resize(r - l + 1);        merge(tree[lc].begin(), tree[lc].end(),              tree[rc].begin(), tree[rc].end(), tree[o].begin());    }}void query(int o, int l, int r, int ql, int qr) {    if ( ql <= l && r <= qr ) {        nodes.push_back(o);        return;    }    int m = (l + r) >> 1;    if ( ql <= m )        query(lc, l, m, ql, qr);    if ( qr > m )        query(rc, m + 1, r, ql, qr);}int cnt(int key) {    int ret = 0;    for (int i = 0; i < nodes.size(); ++i) {        const vector<int> &v = tree[nodes[i]];        ret += lower_bound(v.begin(), v.end(), key) - v.begin();    }    return ret;}int main() {#ifdef _LOCA_ENV_    freopen("input.in", "r", stdin);#endif // _LOCA_ENV    scanf("%d%d", &n, &m);    build(1, 1, n);    vector<int> vals = tree[1];    vals.resize( unique(vals.begin(), vals.end()) - vals.begin() );    rep(ri, 1, m) {        int x, y, k;        scanf("%d%d%d", &x, &y, &k);        int l = 0, r = vals.size(), m;        nodes.clear();        query(1, 1, n, x, y);        // 这里的复杂度        // logn * logn * logn        while ( l < r ) {            m = (l + r) >> 1;            int tmp = cnt(vals[m]);            if ( tmp < k )                l = m + 1;            else                r = m;        }        printf("%d\n", vals[r-1]);    }    return 0;}
0 0