• 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;
    }
  • 相关阅读:
    leetcode Remove Linked List Elements
    leetcode Word Pattern
    leetcode Isomorphic Strings
    leetcode Valid Parentheses
    leetcode Remove Nth Node From End of List
    leetcode Contains Duplicate II
    leetcode Rectangle Area
    leetcode Length of Last Word
    leetcode Valid Sudoku
    leetcode Reverse Bits
  • 原文地址:https://www.cnblogs.com/kls123/p/10752491.html
Copyright © 2020-2023  润新知