zoukankan      html  css  js  c++  java
  • P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)

    题意:带修求区间k小

    题解:回忆在使用主席树求区间k小时 利用前缀和的思想 既然是前缀和 那么我们可以使用更擅长维护前缀和的树状数组

       但是这里每一颗权值线段树就不是带版本的 而是维护数组里i号点的权值信息 所以实际上并不是主席树 每一棵和前面一棵并没有共用结点

       对于一次修改操作 我们先删去这个点的原信息 再更新进去 树状数组上的点一起跳 可能看代码比较好理解一点

       这个方法限制性也很强 必须离线

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 2;
    
    int n, m, len, cnt;
    int a[100005];
    int b[200005];
    int sum[MAXN * 400];
    int ls[MAXN * 400];
    int rs[MAXN * 400];
    int t[MAXN];
    int temp[2][50];
    int tot1, tot0;
    
    struct node {
        char opt;
        int u, v, w;
    }E[100005];
    
    void add(int &o, int l, int r, int k, int v) {
        if(!o) o = ++cnt;
        sum[o] += v;
        int mid = l + r >> 1;
        if(l == r) return;
    
        if(k <= mid) add(ls[o], l, mid, k, v);
        else add(rs[o], mid + 1, r, k, v);
    }
    
    void update(int x, int pos, int v) {
        for(int i = x; i <= n; i += (i & -i)) add(t[i], 1, len, pos, v);
    }
    
    void prepare_query(int l, int r) {
        tot1 = tot0 = 0;
        for(int i = r; i >= 1; i -= (i & -i)) temp[1][++tot1] = t[i];
        for(int i = l; i >= 1; i -= (i & -i)) temp[0][++tot0] = t[i];
    }
    
    int query(int l, int r, int k) {
        if(l == r) return l;
    
        int mid = l + r >> 1;
        int res = 0;
        for(int i = 1; i <= tot1; i++) res += sum[ls[temp[1][i]]];
        for(int i = 1; i <= tot0; i++) res -= sum[ls[temp[0][i]]];
        if(res >= k) {
            for(int i = 1; i <= tot1; i++) temp[1][i] = ls[temp[1][i]];
            for(int i = 1; i <= tot0; i++) temp[0][i] = ls[temp[0][i]];
            return query(l, mid, k);
        } else {
            for(int i = 1; i <= tot1; i++) temp[1][i] = rs[temp[1][i]];
            for(int i = 1; i <= tot0; i++) temp[0][i] = rs[temp[0][i]];
            return query(mid + 1, r, k - res);
        }
    }
    
    char s[5];
    int main() {
        cnt = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
        len = n;
        
        for(int i = 1; i <= m; i++) {
            scanf("%s", s);
            E[i].opt = s[0];
            if(E[i].opt == 'Q') scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
            else {
                scanf("%d%d", &E[i].u, &E[i].v);
                b[++len] = E[i].v;
            }
        }
        sort(b + 1, b + 1 + len);
        len = unique(b + 1, b + 1 + len) - b - 1;
    
        for(int i = 1; i <= n; i++) {
            int tt = lower_bound(b + 1, b + 1 + len, a[i]) - b;
            update(i, tt, 1);
        }
    
        for(int i = 1; i <= m; i++) {
            if(E[i].opt == 'Q') {
                prepare_query(E[i].u - 1, E[i].v);
                printf("%d
    ", b[query(1, len, E[i].w)]);
            } else {
                int t1 = lower_bound(b + 1, b + 1 + len, a[E[i].u]) - b;
                update(E[i].u, t1, -1);
                a[E[i].u] = E[i].v;
                int t2 = lower_bound(b + 1, b + 1 + len, a[E[i].u]) - b;
                update(E[i].u, t2, 1);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HMM MEMM CRF 差别 联系
    JSTL简单介绍
    java基础&amp;&amp;高薪面试
    oracle-Normal
    oracle-Oradim
    oralce管理命令
    oracle默认日期格式
    oralce默认语言
    oracle国家字符集
    oracle-字符集
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11315693.html
Copyright © 2011-2022 走看看