P2617 Dynamic Rankings

P2617 Dynamic Rankings

题意:

给定一个含有 n个数的序列 a1,a2…an,需要支持两种操作:

  • Q l r k 表示查询下标在区间 [l,r] 中的第 k 小的数
  • C x y 表示将 ax改为 y
题解:

A:带修改的主席树怎么写?

B:你会树状数组吗?

A: 只到一点点。

B: 如果你会树状数组一分钟就学会了。 普通的主席树是维护1到i每个版本的信息, 类似与前缀和, 树状数组也是维护前缀和的东西, 如果把之前的前缀和换成 树状数组的前缀和就可以再 log(n)的时间修改和查询。

A: 我取研究一下。

代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 100007;
#define m (l + r) / 2
struct hjt{
    int l, r, sum;
}tree[400 * N];

struct qu{
    int l, r, k;
}que[N];


int top = 1, n, q, a[N], rt[N];
vector<int>g;

int get_id(int x) {
    return lower_bound(g.begin(), g.end(), x) - g.begin() + 1;
}

int lowbit(int x) {
    return x&-x;
}



void update(int num, int v, int &now, int l, int r) {
    if (!now) now = top++;
    tree[now].sum += num;
    if (l == r)return;
    if (v <= m) update(num, v, tree[now].l, l, m);
    else update(num, v, tree[now].r, m + 1, r);
}


int query(int k, vector<int> &last, vector<int> &now, int l, int r) {
    if (l == r) return l;
    int sum = 0;

    for (int i = 0; i < now.size(); i++) {
        sum += tree[tree[now[i]].l].sum;
    }
    for (int i = 0; i < last.size(); i++) {
        sum -= tree[tree[last[i]].l].sum;
    }

    if (sum >= k) {
        for (int i = 0; i < now.size(); i++) {
            now[i] = tree[now[i]].l;
        }
        for (int i = 0; i < last.size(); i++) {
            last[i] = tree[last[i]].l;
        }
        return query(k, last, now, l, m);
    }

    for (int i = 0; i < now.size(); i++) {
        now[i] = tree[now[i]].r;
    }
    for (int i = 0; i < last.size(); i++) {
        last[i] = tree[last[i]].r;
    }
    return query(k - sum, last, now, m + 1, r);
}

void add(int x, int va, int nu) {
    while (x <= n) {
        update(nu, va, rt[x], 1, (int)g.size());
        x += lowbit(x);
    }
}

int ask (int l, int r, int k) {
    vector<int> last, now;
    int x = l - 1;
    while (x > 0) {
        last.push_back(rt[x]);
        x -= lowbit(x);
    }
    x = r;
    while (x > 0) {
        now.push_back(rt[x]);
        x -= lowbit(x);
    }
    return query(k, last, now, 1, (int)g.size());
}


int main(){
   
    scanf("%d %d", &n, &q);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        g.push_back(a[i]);
    }
    for (int i = 1; i <= q; i++) {
        char op;
        scanf(" %c", &op);
        if (op == 'Q') {
            int l, r, k;
            scanf("%d %d %d", &l, &r, &k);
            que[i] = (qu){l, r, k};
        } else {
            int l, r;
            scanf("%d %d", &l, &r);
            que[i] = (qu){0, l, r};
            g.push_back(r);
        }
    }
    sort(g.begin(), g.end());
    g.erase(unique(g.begin(), g.end()), g.end());
    for (int i = 1; i <= n; i++) {
        int va = get_id(a[i]);
        add(i, va, 1);
    }

    for (int i = 1; i <= q; i++) {
        if (que[i].l) {
            printf("%d\n" , g[ask(que[i].l, que[i].r, que[i].k) - 1]);
        }else{
            int va = get_id(a[que[i].r]);
            add(que[i].r, va, -1);
            va = get_id(que[i].k);
            add(que[i].r, va, 1);
            a[que[i].r] = que[i].k;
        }
    }

    
    
}
posted @ 2020-07-10 15:04  ccsu_zhaobo  阅读(42)  评论(0编辑  收藏  举报