BZOJ1901: Zju2112 Dynamic Rankings

【传送门:BZOJ1901


简要题意:

  给出一个长度为n的序列,有两种操作,m个操作:

  Q l r k求出l到r第k小的值

  C x c将第x个数变成c


题解:

  带修主席树例题,用树状数组来维护修改


参考代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
int a[11000];
struct node
{
    int lc,rc,c;
}tr[3100000];int cnt;
int rt[110000];int n;
int ust[110000];
int lowbit(int x){return x&-x;}
void link(int &u,int l,int r,int p,int c)
{
    if(u==0) u=++cnt;
    tr[u].c+=c;
    if(l==r) return ;
    int mid=(l+r)/2;
    if(p<=mid) link(tr[u].lc,l,mid,p,c);
    else link(tr[u].rc,mid+1,r,p,c);
}
void merge(int &u1,int u2)
{
    if(u1==0){u1=u2;return ;}
    if(u2==0) return ;
    tr[u1].c+=tr[u2].c;
    merge(tr[u1].lc,tr[u2].lc);
    merge(tr[u1].rc,tr[u2].rc);
}
void Turn(int u,int c)
{
    while(u>=n+1)
    {
        if(c==-1) ust[u]=rt[u];
        else if(c==0) ust[u]=tr[ust[u]].lc;
        else if(c==1) ust[u]=tr[ust[u]].rc;
        u-=lowbit(u);
    }
}
void change(int u,int p,int c)
{
    while(u<=2*n)
    {
        link(rt[u],0,1000000000,p,c);
        u+=lowbit(u);
    }
}
int getsum(int u)
{
    int ret=0;
    while(u>=n+1)
    {
        ret+=tr[tr[ust[u]].lc].c;
        u-=lowbit(u);
    }
    return ret;
}
int findkth(int u1,int u2,int p1,int p2,int l,int r,int p)
{
    if(l==r) return l;
    int c=tr[tr[u2].lc].c-tr[tr[u1].lc].c+getsum(p2+n)-getsum(p1+n);
    int mid=(l+r)/2;
    if(p<=c)
    {
        Turn(p1+n,0);
        Turn(p2+n,0);
        return findkth(tr[u1].lc,tr[u2].lc,p1,p2,l,mid,p);
    }
    else
    {
        Turn(p1+n,1);
        Turn(p2+n,1);
        return findkth(tr[u1].rc,tr[u2].rc,p1,p2,mid+1,r,p-c);
    }
}
int main()
{
    int m;
    scanf("%d%d",&n,&m);
    cnt=0;memset(rt,0,sizeof(rt));
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        link(rt[i],0,1000000000,a[i],1);
        merge(rt[i],rt[i-1]);
    }
    char st[2];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",st+1);
        if(st[1]=='Q')
        {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            Turn(l+n-1,-1);
            Turn(r+n,-1);
            printf("%d\n",findkth(rt[l-1],rt[r],l-1,r,0,1000000000,k));
        }
        else
        {
            int p,c;
            scanf("%d%d",&p,&c);
            change(p+n,a[p],-1);
            a[p]=c;
            change(p+n,a[p],1);
        }
    }
    return 0;
}

 

posted @ 2018-04-10 15:29  Star_Feel  阅读(166)  评论(0编辑  收藏  举报