zoukankan      html  css  js  c++  java
  • luogu P2617 Dynamic Rankings && bzoj 1901 (带修改区间第k大)

    链接:https://www.luogu.org/problemnew/show/P2617

    思路:

    如果直接在主席树上修改的话,每次修改都会对后面所有的树造成影响,一次修改的复杂度就会变成 : n*logn,我们套上树状数组维护,每次就最多只用更新logn棵树,复杂度是:logn*logn,是可以接受的;

    代码参考hzwer: http://hzwer.com/2835.html

    实现代码;

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 2e5+10;
    int v[M],num[M*2],has[M*2];
    int op[M],A[M],B[M],K[M],rt[M];
    int sum[M*170],ls[M*170],rs[M*170];
    int L[40],R[40],a,b,tot,idx,k;
    
    int lowbit(int x){
        return x&(-x);
    }
    
    int find(int x){
        int l = 1,r = tot;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(has[mid] < x) l = mid + 1;
            else r = mid - 1;
        }
        return l;
    }
    
    void update(int old,int &k,int p,int c,int l,int r){
        k = ++idx;
        ls[k] = ls[old],rs[k] = rs[old];
        sum[k] = sum[old] + c;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        if(p <= mid) update(ls[old],ls[k],p,c,l,mid);
        else update(rs[old],rs[k],p,c,mid+1,r);
    }
    
    int query(int l,int r,int k){
        if(l == r) return l;
        int suml = 0,sumr = 0;
        for(int i = 1;i <= a;i ++) suml += sum[ls[L[i]]];
        for(int i = 1;i <= b;i ++) sumr += sum[ls[R[i]]];
        int mid = (l + r) >> 1;
        if(sumr - suml >= k){
            for(int i = 1;i <= a;i ++) L[i] = ls[L[i]];
            for(int i = 1;i <= b;i ++) R[i] = ls[R[i]];
            return query(l,mid,k);
        }
        else {
            for(int i = 1;i <= a;i ++) L[i] = rs[L[i]];
            for(int i = 1;i <= b;i ++) R[i] = rs[R[i]];
            return query(mid+1,r,k-(sumr-suml));
        }
    }
    
    int main()
    {
        int n,m,cnt = 0;
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i ++){
            scanf("%d",&v[i]);
            num[++cnt] = v[i];
        }
        char s[10];
        for(int i = 1;i <= m;i ++){
            scanf("%s",s);
            scanf("%d%d",&A[i],&B[i]);
            if(s[0]=='Q') scanf("%d",&K[i]),op[i] = 1;
            else num[++cnt] = B[i];
        }
        sort(num+1,num+cnt+1);
        has[++tot] = num[1];
        for(int i = 2;i <= cnt;i ++){
            if(num[i] != num[i-1])
                has[++tot] = num[i];
        }
        for(int i = 1;i <= n;i ++){
            int k = find(v[i]);
            for(int j = i;j <= n;j += lowbit(j))
                update(rt[j],rt[j],k,1,1,tot);
        }
        for(int i = 1;i <= m;i ++){
            if(op[i]){
                a = 0; b = 0; A[i]--;
                for(int j = A[i];j > 0;j -= lowbit(j))
                    L[++a] = rt[j];
                for(int j = B[i];j > 0;j -= lowbit(j))
                    R[++b] = rt[j];
                printf("%d
    ",has[query(1,tot,K[i])]);
            }
            else{
                int k = find(v[A[i]]);
                for(int j = A[i];j <= n;j += lowbit(j))
                    update(rt[j],rt[j],k,-1,1,tot);
                v[A[i]] = B[i];
                k = find(B[i]);
                for(int j = A[i];j <= n;j += lowbit(j))
                    update(rt[j],rt[j],k,1,1,tot);
            }
        }
        return 0;
    }
  • 相关阅读:
    终端提示符路径长度设置
    linux ssh服务器
    kail-linux my need
    elasticsearch的marvel
    VPS折腾
    Ubuntu 系统密码相关问题
    Pycharm 使用配置
    python集成开发工具
    Codeforces Round #554 (Div. 2) 选做
    Codeforces Forethought Future Cup Elimination Round 选做
  • 原文地址:https://www.cnblogs.com/kls123/p/10752491.html
Copyright © 2011-2022 走看看