「Luogu P2617」Dynamic Rankings

给出一段序列,每次修改某个数的值和询问区间第 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;
}
posted @ 2020-02-03 23:15  小蒟蒻hlw  阅读(80)  评论(0)    收藏  举报