Dynamic Rankings ZOJ - 2112 树套树 带修改主席树

求区间第K大,很简单——-主席树即可;
那么如果增加一个修改操作,又该怎么处理呢?
单点修改—-很容易想到 树状数组;

此时树状数组每个节点存的是一颗空树;

详细的解释,说明

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 60005
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
typedef long long  ll;
typedef unsigned long long ull;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define sq(x) (x)*(x)
#define eps 1e-6
const int N = 2500005;

inline int read()
{
    int x = 0, k = 1; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-')k = -1; c = getchar(); }
    while (c >= '0' && c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return x * k;
}

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}

int a[maxn], b[maxn], rt[maxn], num, f[maxn], used[maxn];
int cnt, sum[N], ls[N], rs[N], n, q[10005][4];

void build(int &id, int l, int r) {
    id = ++cnt;
    sum[id] = 0;
    if (l == r)return;
    int mid = (l + r)/2;
    build(ls[id], l, mid); build(rs[id], mid + 1, r);
}

void upd(int &id, int l, int r, int last, int val, int k) {
    id = ++cnt;
    ls[id] = ls[last]; rs[id] = rs[last];
    sum[id] = sum[last] + k;
    if (l == r)return;
    int mid = (l + r) /2;
    if (val <= mid)
        upd(ls[id], l, mid, ls[last], val, k);
    else
        upd(rs[id], mid + 1, r, rs[last], val, k);
}

int Sum(int x) {
    int ans = 0;
    while (x) {
        ans += sum[ls[used[x]]];
        x -= x & -x;
    }
    return ans;
}

int query(int st, int ed, int val) {
    int i, les, res;
    int l = 1, r = num;
    les = rt[st]; res = rt[ed];
    for (i = st; i > 0; i -= i & -i)used[i] = f[i];
    for (i = ed; i > 0; i -= i & -i)used[i] = f[i];

    while (l < r) {
        int mid = (l + r)>>1;
        int tmp = Sum(ed) - Sum(st) + sum[ls[res]] - sum[ls[les]];
        if (val <= tmp) {
            r = mid;
            for (i = st; i > 0; i -= i & -i) {
                used[i] = ls[used[i]];
            }
            for (i = ed; i > 0; i -= i & -i) {
                used[i] = ls[used[i]];
            }
            les = ls[les]; res = ls[res];
        }
        else {
            l = mid + 1; val -= tmp;
            for (i = st; i > 0; i -= i & -i)used[i] = rs[used[i]];
            for (i = ed; i > 0; i -= i & -i)used[i] = rs[used[i]];
            les = rs[les]; res = rs[res];
        }
    }
    return l;
}

void add(int x, int v, int k) {
    while (x<=n)
    {
        int tmp = f[x];
        upd(f[x], 1, num, tmp, v, k); x += x & -x;
    }
}

int main()
{
    char c;
    int T, m, i, j;
    cin >> T;
    while (T--) {
        cnt = 0;
        //ms(sum);
        memset(sum, 0, sizeof(sum));
        cin >> n >> m;
        for (i = 1; i <= n; i++) {
            scanf("%d", &a[i]); b[i] = a[i];
        }
        num = n;
        for (i = 1; i <= m; i++) {
            cin >> c;
            if (c == 'Q') {
                //q[i][1] = read(); q[i][2] = read(); q[i][3] = read();
                scanf("%d%d%d", &q[i][1], &q[i][2], &q[i][3]);
                q[i][0] = 1;
            }
            else {
                q[i][1] = read(); q[i][2] = read();
                b[++num] = q[i][2]; q[i][0] = 0;
            }
        }
        sort(b + 1, b + num + 1);
        num = unique(b + 1, b + num + 1) - b - 1;

        for (i = 1; i <= num; i++) {
            a[i] = lower_bound(b + 1, b + num + 1, a[i]) - b;
        }

        build(rt[0], 1, num);

        for (i = 1; i <= n; i++) {
            upd(rt[i], 1, num, rt[i - 1], a[i], 1);
        }
        for (i = 1; i <= n; i++)f[i] = rt[0];
        for (i = 1; i <= m; i++) {
            if (q[i][0]==1) {
                int ans = query(q[i][1] - 1, q[i][2] , q[i][3]);
                //cout << b[ans] << endl;
                printf("%d\n", b[ans]);
            }
            else {
                int tmp;
                add(q[i][1], a[q[i][1]], -1);
                tmp = lower_bound(b + 1, b + num + 1,q[i][2]) - b;
                add(q[i][1], tmp, 1);
                a[q[i][1]] = tmp;
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值