码迷,mamicode.com
首页 > 其他好文 > 详细

「Luogu P2617」Dynamic Rankings

时间:2020-02-04 00:46:40      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:com   inline   insert   return   dynamic   ++i   ++   ranking   序列   

给出一段序列,每次修改某个数的值和询问区间第 k 小。\((1\le n,m\le 10^5,0\le a_i\le10^9)\)

Luogu

分析

动态主席树裸题。

树状数组套主席树,树状数组的每个结点相当于一棵主席树,每次修改操作只在对应树状数组的 logn 个结点所对应的主席树上修改,查询时,将 l - 1 和 r 分别对应的 logn 棵主席树作差即可。

时间复杂度: \(O(n\log^2{n})\)

空间复杂度: \(O(n\log{n})\)

代码

#include <bits/stdc++.h>

#define N 100005
#define lowbit(i) i&-i
#define REP(i, l, r) for (int i = (l); i != (r); ++i)
#define FOR(i, l, r) for (int i = (l); i <= (r); ++i)
#define DRP(i, l, r) for (int i = (l); i != (r); --i)
#define DFR(i, l, r) for (int i = (l); i >= (r); --i)

using namespace std;

int gi() {
    int x = 0, f = 1; char c = getchar();
    for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

struct updates { int a, b, k, d; } q[N];

int n, m, tot, len, sx, sy;
int s[N], hs[N << 1], rx[N], ry[N];
int rt[N], cnt[N << 10], L[N << 10], R[N << 10];

void insert(int lst, int &now, int l, int r, int k, int v) {
    if (!now) now = ++tot;
    cnt[now] = cnt[lst] + v;
    if (l == r) return;
    int mid = l + r >> 1;
    if (k <= mid) R[now] = R[lst], insert(L[lst], L[now], l, mid, k, v);
    else L[now] = L[lst], insert(R[lst], R[now], mid + 1, r, k, v);
}

void modify(int i, int v) {
    int k = lower_bound(hs + 1, hs + 1 + len, s[i]) - hs;
    while (i <= n) {
        insert(rt[i], rt[i], 1, len, k, v);
        i += lowbit(i);
    }
}

void get(int x, int y) {
    sx = sy = 0;
    while (x) rx[++sx] = rt[x], x -= lowbit(x);
    while (y) ry[++sy] = rt[y], y -= lowbit(y);
}

int query(int l, int r, int k) {
    if (l == r) return l;
    int sum = 0;
    FOR(i, 1, sx) sum -= cnt[L[rx[i]]];
    FOR(i, 1, sy) sum += cnt[L[ry[i]]];
    int mid = l + r >> 1;
    if (k <= sum) {
        FOR(i, 1, sx) rx[i] = L[rx[i]];
        FOR(i, 1, sy) ry[i] = L[ry[i]];
        return query(l, mid, k);
    }
    else {
        FOR(i, 1, sx) rx[i] = R[rx[i]];
        FOR(i, 1, sy) ry[i] = R[ry[i]];
        return query(mid + 1, r, k - sum);
    }
}

int main() {
    char ch;
    len = n = gi(), m = gi();
    FOR(i, 1, n) s[i] = hs[i] = gi();
    FOR(i, 1, m) {
        cin >> ch;
        if (ch == 'Q') q[i] = (updates){gi(), gi(), gi(), 1};
        else q[i] = (updates){gi(), hs[++len] = gi(), 0, 0};
    }
    sort(hs + 1, hs + 1 + len);
    len = unique(hs + 1, hs + 1 + len) - hs - 1;
    FOR(i, 1, n) modify(i, 1);
    FOR(i, 1, m) {
        if (q[i].d) {
            get(q[i].a - 1, q[i].b);
            printf("%d\n", hs[query(1, len, q[i].k)]);
        }
        else {
            modify(q[i].a, -1);
            s[q[i].a] = q[i].b;
            modify(q[i].a, 1);
        }
    }
    return 0;
}

「Luogu P2617」Dynamic Rankings

标签:com   inline   insert   return   dynamic   ++i   ++   ranking   序列   

原文地址:https://www.cnblogs.com/hlw1/p/12257988.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!