zoj2112 Dynamic Rankings 动态区间第k大,树状数组套平衡树

 

 

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n,m;
int a[maxn];
char op[5];int L,R,k,p,c;

///---treap
struct Node
{
    int ch[2];
    int r,v;
    int sz;
};Node tr[maxn];int rt[maxn];
int tot1;
int s[maxn],tot2;

int newnode()
{
    int o;
    if(tot2) o=s[tot2--];
    else o=++tot1;
    tr[o].ch[0]=tr[o].ch[1]=-1;
    tr[o].r=rand();tr[o].v=0;
    tr[o].sz=1;
    return o;
}

void up(int o)
{
    tr[o].sz=1;
    if(~tr[o].ch[0]) tr[o].sz+=tr[tr[o].ch[0]].sz;
    if(~tr[o].ch[1]) tr[o].sz+=tr[tr[o].ch[1]].sz;
}

void rot(int &o,int d)
{
    int k=tr[o].ch[d^1];
    tr[o].ch[d^1]=tr[k].ch[d];
    tr[k].ch[d]=o;
    up(o);up(k);
    o=k;
}

void Insert(int &o,int x)
{
    if(o==-1){
        o=newnode();
        tr[o].v=x;
        return;
    }
    int d=x<tr[o].v?0:1;
    Insert(tr[o].ch[d],x);
    if(tr[tr[o].ch[d]].r>tr[o].r) rot(o,d^1);
    up(o);
}

void Remove(int &o,int x)
{
    if(o==-1) return;
    if(tr[o].v==x){
        if(tr[o].ch[0]==-1) s[++tot2]=o,o=tr[o].ch[1];
        else if(tr[o].ch[1]==-1) s[++tot2]=o,o=tr[o].ch[0];
        else{
            int d=tr[tr[o].ch[0]].r>tr[tr[o].ch[1]].r?0:1;
            rot(o,d^1);
            Remove(tr[o].ch[d^1],x);
        }
        if(~o) up(o);
        return;
    }
    if(x<tr[o].v) Remove(tr[o].ch[0],x);
    else Remove(tr[o].ch[1],x);
    if(~o) up(o);
}

int getcnt(int &o,int y)
{
    if(o==-1) return 0;
    if(y<=tr[o].v) return getcnt(tr[o].ch[0],y);
    int ls=tr[o].ch[0]==-1?0:tr[tr[o].ch[0]].sz;
    return ls+1+getcnt(tr[o].ch[1],y);
}

int getcnt2(int &o,int y)
{
    if(o==-1) return 0;
    if(y<tr[o].v) return getcnt(tr[o].ch[0],y);
    int ls=tr[o].ch[0]==-1?0:tr[tr[o].ch[0]].sz;
    return ls+1+getcnt2(tr[o].ch[1],y);
}

///---BIT
int lowbit(int x)
{
    return x&-x;
}

void add(int p,int c)
{
    while(p<=n){
        Insert(rt[p],c);
        p+=lowbit(p);
    }
}

void del(int p,int c)
{
    while(p<=n){
        Remove(rt[p],c);
        p+=lowbit(p);
    }
}

int sum(int p,int y)
{
    int res=0;
    while(p){
        res+=getcnt(rt[p],y);
        p-=lowbit(p);
    }
    return res;
}

int sum2(int p,int y)
{
    int res=0;
    while(p){
        res+=getcnt2(rt[p],y);
        p-=lowbit(p);
    }
    return res;
}

int bin(int L,int R,int l,int r,int k)
{
    while(l<=r){
        int m=(l+r)>>1;
        int cnt=sum(R,m)-sum(L-1,m);
        int cnt2=sum2(R,m)-sum2(L-1,m);
        if(cnt<=k-1&&cnt2>=k) return m;
        if(k>cnt2) l=m+1;
        else r=m-1;
    }
}

void Init()
{
    memset(rt,-1,sizeof(rt));
    tot1=tot2=0;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);
        Init();
        REP(i,1,n) scanf("%d",&a[i]);
        REP(i,1,n) add(i,a[i]);
        while(m--){
            scanf("%s",op);
            if(op[0]=='C'){
                scanf("%d%d",&p,&c);
                del(p,a[p]);
                add(p,c);
                a[p]=c;
            }
            else{
                scanf("%d%d%d",&L,&R,&k);
                printf("%d\n",bin(L,R,0,INF,k));
            }
        }
    }
    return 0;
}
View Code

 

注意下二分要算两个,小于和小于等于的。。。

然后直接树状数组或线段树套上平衡树就可以了。

posted @ 2016-03-07 12:16  __560  阅读(302)  评论(0编辑  收藏  举报