[BZOJ1901]Dynamic Rankings(动态主席树)

来源:互联网 发布:北京java培训 编辑:程序博客网 时间:2024/06/17 20:15

题目描述

传送门

题解

动态主席树模板题,感谢hzwer的模板,自己改动了一点小地方。
这就是传说中的树套树?

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int max_n=1e4+5;const int max_m=1e4+5;const int max_log=30;const int max_tree=3e6+5;char opt[10];int n,m,a,b,t,sz,N,cnt;int val[max_n],A[max_m],B[max_m],K[max_m],flag[max_m];int num[max_n*2],hash[max_n*2],root[max_n*2],L[max_log],R[max_log];int sum[max_tree],ls[max_tree],rs[max_tree];inline int find(int x){    int l=1,r=N,mid;    while (l<=r){        mid=(l+r)>>1;        if (hash[mid]<x) l=mid+1;        else r=mid-1;     }    return l;}inline void build(int last,int l,int r,int &now,int x,int v){    int mid=(l+r)>>1;    now=++sz;    sum[now]=sum[last]+v; ls[now]=ls[last]; rs[now]=rs[last];    if (l==r) return;    if (x<=mid) build(ls[last],l,mid,ls[now],x,v);    else build(rs[last],mid+1,r,rs[now],x,v);}inline int query(int l,int r,int k){    int mid=(l+r)>>1;    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]]];    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(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;++i) scanf("%d",&val[i]),num[++cnt]=val[i];    for (int i=1;i<=m;++i){        scanf("%s",opt);        if (opt[0]=='C'){            scanf("%d%d",&A[i],&B[i]);            num[++cnt]=B[i];        }        else{            flag[i]=1;            scanf("%d%d%d",&A[i],&B[i],&K[i]);        }    }    sort(num+1,num+cnt+1);    hash[++N]=num[1];    for (int i=2;i<=cnt;++i)      if (num[i]!=num[i-1]) hash[++N]=num[i];    for (int i=1;i<=n;++i){        t=find(val[i]);        for (int j=i;j<=n;j+=j&(-j))          build(root[j],1,N,root[j],t,1);    }    for (int i=1;i<=m;++i)      if (flag[i]){        a=0,b=0,A[i]--;        for (int j=A[i];j>=1;j-=j&(-j)) L[++a]=root[j];        for (int j=B[i];j>=1;j-=j&(-j)) R[++b]=root[j];        printf("%d\n",hash[query(1,N,K[i])]);      }      else{        t=find(val[A[i]]);        for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,-1);        val[A[i]]=B[i];        t=find(val[A[i]]);        for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,1);      }}
0 0