动态第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;
}

 

posted @ 2019-01-29 16:16  Tartarus_li  阅读(540)  评论(0编辑  收藏  举报