BZOJ 1901: Zju2112 Dynamic Rankings【带修改主席树模板】

1901: Zju2112 Dynamic Rankings

【题目描述】
传送门

【题解】

带修改主席树模板。

代码如下

#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 10005
using namespace std;
int n,m,Len,tot,a[MAXN],hsh[MAXN<<1];
int use[MAXN],S[MAXN],Rot[MAXN],L[MAXN*600],R[MAXN*600],Sum[MAXN*600];
struct xcw{int l,r,k;bool Q;}T[MAXN];
int read(){
    int ret=0;bool f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
    for(; isdigit(ch);ch=getchar()) ret=(ret<<3)+(ret<<1)+ch-48;
    return f?ret:-ret;
}
int Build(int l,int r){
    int rt=++tot;Sum[rt]=0;
    if(l^r){
        int mid=(r+l)>>1;
        L[rt]=Build(l,mid),R[rt]=Build(mid+1,r);
    }
    return rt;
}
int Updata(int Lst,int l,int r,int x,int p){
    int rt=++tot;
    Sum[rt]=Sum[Lst]+p,L[rt]=L[Lst],R[rt]=R[Lst];
    if(l<r){
        int mid=(r+l)>>1;
        if(x<=mid) L[rt]=Updata(L[Lst],l,mid,x,p);
        else R[rt]=Updata(R[Lst],mid+1,r,x,p);
    }
    return rt;
}
void Add(int x,int Num,int p){for(int i=x;i<=n;i+=i&-i) S[i]=Updata(S[i],1,Len,Num,p);}
int Get(int x){
    int Ret=0;
    for(int i=x;i;i-=i&-i) Ret+=Sum[L[use[i]]];
    return Ret;
}
int Query(int u,int v,int lt,int rt,int l,int r,int p){
    if(l>=r) return l;
    int mid=(r+l)>>1,Now=Get(v)-Get(u)+Sum[L[rt]]-Sum[L[lt]];
    if(Now>=p){
        for(int i=u;i;i-=i&-i) use[i]=L[use[i]];
        for(int i=v;i;i-=i&-i) use[i]=L[use[i]];
        return Query(u,v,L[lt],L[rt],l,mid,p);
    }else{
        for(int i=u;i;i-=i&-i) use[i]=R[use[i]];
        for(int i=v;i;i-=i&-i) use[i]=R[use[i]];
        return Query(u,v,R[lt],R[rt],mid+1,r,p-Now);
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("prob.in","r",stdin);
    freopen("prob.out","w",stdout);
    #endif
    n=read();m=read();
    for(int i=1;i<=n;i++) a[i]=read(),hsh[++Len]=a[i];
    for(int i=1;i<=m;i++){
        char Q[10];scanf("%s",Q);
        if(Q[0]=='Q') T[i].l=read(),T[i].r=read(),T[i].k=read(),T[i].Q=1;
        else T[i].l=read(),T[i].r=read(),T[i].Q=0,hsh[++Len]=T[i].r;
    }
    sort(hsh+1,hsh+1+Len);Len=unique(hsh+1,hsh+1+Len)-hsh-1;
    Rot[0]=Build(1,Len);
    for(int i=1;i<=n;i++) Rot[i]=Updata(Rot[i-1],1,Len,lower_bound(hsh+1,hsh+1+Len,a[i])-hsh,1);
    for(int i=1;i<=n;i++) S[i]=Rot[0];
    for(int i=1;i<=m;i++){
        if(T[i].Q){
            for(int j=T[i].l-1;j;j-=j&-j) use[j]=S[j];
            for(int j=T[i].r;j;j-=j&-j) use[j]=S[j];
            printf("%d\n",hsh[Query(T[i].l-1,T[i].r,Rot[T[i].l-1],Rot[T[i].r],1,Len,T[i].k)]);
        }else{
            Add(T[i].l,lower_bound(hsh+1,hsh+1+Len,a[T[i].l])-hsh,-1);
            Add(T[i].l,lower_bound(hsh+1,hsh+1+Len,T[i].r)-hsh,1);
            a[T[i].l]=T[i].r;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值