BZOJ1901 - Dynamic Rankings(树状数组套主席树)

题目大意

给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下:

Q l r k 要求你查询区间[l,r]第k小的数是哪个

C i t  要求你把第i个数修改为t

题解

动态的区间第k小,如果还是按照静态的主席树做的话,每次修改需要对n个线段树进行修改,这样显然会TLE,所以我们需要用树状数组,这样每次只需要对logn颗线段树修改即可,修改的时间复杂度为logn^2,询问的时间复杂度为logn^2,空间复杂度为nlogn^2

还有一种空间复杂度为nlogn+mlogn^2的方法,就是先建立n颗静态的主席树,空间复杂度为nlogn,然后再更新的时候用树状数组套线段树,这样空间复杂度为mlogn^2,所以总空间复杂度为nlogn+mlogn^2

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

#define MAXN 140000

#define NN 10005

#define lson l,m,ls[s]

#define rson m+1,r,rs[s]

int ls[20*MAXN],rs[20*MAXN],cnt[20*MAXN];

int T[MAXN],tot;

int len,n,m;

int num[MAXN];

char op[10010][3];

int a[NN*2],lt[NN],rt[NN],K[NN];

int L[30],R[30];

int N,M;

void build(int l,int r,int &s)

{

    s=++tot;

    cnt[s]=0;

    if(l==r) return;

    int m=(l+r)>>1;

    build(lson);

    build(rson);

}

void update(int last,int p,int l,int r,int &s,int d)

{

    s=++tot;

    ls[s]=ls[last],rs[s]=rs[last],cnt[s]=cnt[last]+d;

    if(l==r) return;

    int m=(l+r)>>1;

    if(p<=m) update(ls[last],p,lson,d);

    else     update(rs[last],p,rson,d);



}

int query(int l,int r,int k)

{

    if(l==r) return r;

    int suma=0,sumb=0;

    for(int i=1; i<=N; i++) suma+=cnt[ls[L[i]]];

    for(int i=1; i<=M; i++) sumb+=cnt[ls[R[i]]];

    int m=(l+r)>>1,sum=sumb-suma;

    if(sum>=k)

    {

        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,m,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(m+1,r,k-sum);

    }

}

int lowbit(int x)

{

    return x&-x;

}

void BIT(int x,int value,int d)

{

    while(x<=n)

    {

        update(T[x],value,1,len,T[x],d);

        x+=lowbit(x);

    }

}

int BIT_query(int l,int r,int k)

{

    N=0,M=0;

    while(l>0)

    {

        L[++N]=T[l];

        l-=lowbit(l);

    }

    while(r>0)

    {

        R[++M]=T[r];

        r-=lowbit(r);

    }

    return query(1,len,k);

}

int main()

{

    scanf("%d%d",&n,&m);

    for(int i=1; i<=n; i++)

    {

        scanf("%d",&num[i]);

        a[++len]=num[i];

    }

    for(int i=1; i<=m; i++)

    {

        scanf("%s%d%d",op[i],&lt[i],&rt[i]);

        if(op[i][0]=='Q') scanf("%d",&K[i]);

        else

            a[++len]=rt[i];

    }

    sort(a+1,a+len+1);

    len=unique(a+1,a+len+1)-a-1;

    for(int i=1; i<=n; i++) num[i]=lower_bound(a+1,a+1+len,num[i])-a;

    build(1,len,T[0]);

    for(int i=1; i<=n; i++) BIT(i,num[i],1);

    for(int i=1; i<=m; i++)

        if(op[i][0]=='Q')

            printf("%d\n",a[BIT_query(lt[i]-1,rt[i],K[i])]);

        else

        {

            BIT(lt[i],num[lt[i]],-1);

            int pos=lower_bound(a+1,a+len+1,rt[i])-a;

            num[lt[i]]=pos;

            BIT(lt[i],pos,1);

        }

    return 0;

}

你可能感兴趣的:(dynamic)