bzoj1901 线段树套主席树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#define maxn 120000
using namespace std;
int ls[maxn*20],rs[maxn*20],sum[maxn*20];
int root[maxn],tot;
void update(int fa,int p,int l,int r,int &rt,int v){
    rt=++tot;
    ls[rt]=ls[fa],rs[rt]=rs[fa],sum[rt]=sum[fa]+v;
    if(l==r)return;
    int mid=l+r>>1;
    if(p<=mid)update(ls[fa],p,l,mid,ls[rt],v);
    else update(rs[fa],p,mid+1,r,rs[rt],v);
}
int cc,n,m;
int num[maxn];
char op[maxn];
#define NN 10010
int san[NN*2],P[NN],Q[NN],K[NN];
int L[30],R[30];
int N,M;
int query(int l,int r,int k){
    if(l==r)return l;
    int mid=l+r>>1;
    int suma=0,sumb=0;  
    for(int i=1;i<=N;i++)suma+=sum[ls[L[i]]];
    for(int i=1;i<=M;i++)sumb+=sum[ls[R[i]]];
    int del=sumb-suma;
    if(k<=del){
        for(int i=1;i<=N;i++)L[i]=ls[L[i]];
        for(int i=1;i<=M;i++)R[i]=ls[R[i]];
        return query(l,mid,k);
    }else{
        for(int i=1;i<=N;i++)L[i]=rs[L[i]];
        for(int i=1;i<=M;i++)R[i]=rs[R[i]];
        return query(mid+1,r,k-del);
    }
}
int ask(int l,int r,int k){
    N=0,M=0;
    for(;l>0;l-=l&-l)L[++N]=root[l];
    for(;r>0;r-=r&-r)R[++M]=root[r];
    return query(1,cc,k);
}
void change(int x,int val,int v){
    for(;x<=n;x+=x&-x){
        update(root[x],val,1,cc,root[x],v);
    }
}
int sn;
int rank[NN*2];
int rr(int x){
    int l=0,r=cc;
    while(l+1!=r){
        int mid=l+r>>1;
        if(rank[mid]>=x)r=mid;
        else l=mid;
    }
    return r;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&num[i]);
      san[++sn]=num[i]; 
    }
    for(int i=1;i<=m;i++){
        scanf(" %c",&op[i]);
        scanf("%d%d",&P[i],&Q[i]);
        if(op[i]=='Q')scanf("%d",&K[i]);
        else san[++sn]=Q[i];
    }
    sort(san+1,san+sn+1);
    for(int i=1;i<=sn;i++){
        if(i==1||san[i]!=san[i-1])cc++;
        rank[cc]=san[i];
    }
    for(int i=1;i<=n;i++)num[i]=rr(num[i]);

    for(int i=1;i<=n;i++)change(i,num[i],1);
    for(int i=1;i<=m;i++){
        if(op[i]=='Q'){
            int ans=ask(P[i]-1,Q[i],K[i]);
            printf("%d\n",rank[ans]);
        }else{
            change(P[i],num[P[i]],-1);
            num[P[i]]=rr(Q[i]);
            change(P[i],num[P[i]],1);
        }
    }
}

 

posted @ 2014-04-21 11:31  wangyucheng  阅读(...)  评论(...编辑  收藏