zoukankan      html  css  js  c++  java
  • 动态第K大 (树状数组套主席树)

    在静态主席树的基础上,外面套一层树状数组

    主席树就是利用前缀和的性质

    利用树状数组维护前缀和的功能,可以做到 log^2 的复杂度进行单点修改

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<stack>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100010;
    
    int n,m,q;
    int a[maxn],b[maxn*2],qa[maxn],qb[maxn],qc[maxn];
    int rt[maxn*600],lc[maxn*600],rc[maxn*600],sz[maxn*600],tot;
    int xx[maxn],yy[maxn],totx,toty;
    char op[10]; 
    
    void modify(int &i,int o,int l,int r,int p,int k){
        i=++tot;
        lc[i]=lc[o],rc[i]=rc[o],sz[i]=sz[o]+k;
        if(l==r) return;
        int mid=(l+r)/2;
        if(p<=mid) modify(lc[i],lc[i],l,mid,p,k);
        else modify(rc[i],rc[i],mid+1,r,p,k);
    }
    
    void add(int x,int k){
        int p=lower_bound(b+1,b+1+q,a[x])-b;
        for(int i=x;i<=n;i+=i&(-i)){
            modify(rt[i],rt[i],1,q,p,k);
        } 
    }
    
    int query(int l,int r,int k){
        if(l==r) return l;
        int sum=0;
        for(int i=1;i<=toty;i++) sum+=sz[lc[yy[i]]];
        for(int i=1;i<=totx;i++) sum-=sz[lc[xx[i]]];
        
        int mid=(l+r)/2; 
        if(sum>=k){
            for(int i=1;i<=totx;i++) xx[i]=lc[xx[i]];
            for(int i=1;i<=toty;i++) yy[i]=lc[yy[i]];
            return query(l,mid,k);
        }else{
            for(int i=1;i<=totx;i++) xx[i]=rc[xx[i]];
            for(int i=1;i<=toty;i++) yy[i]=rc[yy[i]];
            return query(mid+1,r,k-sum);
        }
    }
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
    
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++) a[i]=read(),b[++q]=a[i];
        
        for(int i=1;i<=m;i++){
            scanf("%s",op);
            qa[i]=read(),qb[i]=read();
            if(op[0]=='Q') qc[i]=read();
            else b[++q]=qb[i];
        }
        
        sort(b+1,b+1+q); 
        q=unique(b+1,b+1+q)-b-1; 
        
        for(int i=1;i<=n;i++) add(i,1);
        for(int i=1;i<=m;i++){
            if(qc[i]){
                totx=toty=0;
                for(int j=qa[i]-1;j>0;j-=j&(-j)) xx[++totx]=rt[j];
                for(int j=qb[i];j>0;j-=j&(-j)) yy[++toty]=rt[j];
                int ans=query(1,q,qc[i]);
                printf("%d\n",b[ans]);
            }else{
                add(qa[i],-1);
                a[qa[i]]=qb[i];
                add(qa[i],1);
            }    
        }
        return 0;
    }
  • 相关阅读:
    二叉树的前中后序遍历(非递归)
    剑指offer——圆圈中最后剩下的数字
    剑指offer——和为s的连续正整数序列
    leetcode300.最长上升子序列
    将网络描述符设置为非阻塞的场景
    leetcode72.编辑距离
    浅谈各种锁机制
    TCP如何保证可靠传输?
    JavaScript(七)
    JavaScript(六)
  • 原文地址:https://www.cnblogs.com/tuchen/p/10334588.html
Copyright © 2011-2022 走看看