主席树——求静态区间第k大

例题:poj2104 http://poj.org/problem?id=2104

讲解,推荐博客:http://blog.sina.com.cn/s/blog_6022c4720102w03t.html

       http://seter.is-programmer.com/posts/31907.html

http://www.cnblogs.com/shenben/p/5598371.html

数组版:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100001;
int l_child[N*18],r_child[N*18],sum[N*18];
int n,m,a[N],hash[N],cnt,root[N];
int x,y,k;
void discrete()
{
    sort(hash+1,hash+n+1);
    cnt=unique(hash+1,hash+n+1)-(hash+1);
    for(int i=1;i<=n;i++) a[i]=lower_bound(hash+1,hash+cnt+1,a[i])-hash;
}
int init()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int query(int x,int y,int l,int r,int k)
{
    if(l==r) return l;
    int mid=l+r>>1,tmp=sum[l_child[y]]-sum[l_child[x]];
    if(tmp>=k) return query(l_child[x],l_child[y],l,mid,k);
    else return query(r_child[x],r_child[y],mid+1,r,k-tmp);
}
int tot=0;
void build(int x,int &y,int l,int r,int v)
{
    sum[y=++tot]=sum[x]+1;
    if(l==r) return;
    int mid=l+r>>1;
    if(v<=mid)
    {
        r_child[y]=r_child[x];
        build(l_child[x],l_child[y],l,mid,v);
    }
    else
    {
        l_child[y]=l_child[x];
        build(r_child[x],r_child[y],mid+1,r,v);
    }
}
int main()
{
    n=init();m=init();
    for(int i=1;i<=n;i++) a[i]=init(),hash[i]=a[i];
    discrete();
    //for(int i=1;i<=n;i++) printf("%d ",a[i]);
    for(int i=1;i<=n;i++) build(root[i-1],root[i],1,cnt,a[i]);
    for(int i=1;i<=m;i++) 
    {
        x=init();y=init();k=init();
        printf("%d\n",hash[query(root[x-1],root[y],1,cnt,k)]);
    }
}

 指针版:TLE

#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int n,m,a[N],hash[N];
int tot,cnt;
struct node
{
    node * l,* r;
    int sum;
};
node * root[N]; 
void discrete()
{
    sort(a+1,a+n+1);
    tot=unique(a+1,a+n+1)-(a+1);
    for(int i=1;i<=n;i++) hash[i]=lower_bound(a+1,a+n+1,hash[i])-a;
}
inline node * build(node * pre,int l,int r,int w)
{
    node *neww=new node();
    //node * neww=(node *)malloc(sizeof(node));
    neww->sum=pre->sum+1;
    if(l==r) return neww;
    int mid=l+r>>1;
    if(w<=mid)
    {
        neww->r=pre->r;
        neww->l=build(pre->l,l,mid,w);
    }
    else
    {
        neww->l=pre->l;
        neww->r=build(pre->r,mid+1,r,w);
    }
    return neww;
}
inline int query(node * x,node * y,int k,int l,int r)
{
    if(l==r) return l;
    int mid=l+r>>1,tmp=y->l->sum-x->l->sum;
    if(k<=tmp) return query(x->l,y->l,k,l,mid);
    else return query(x->r,y->r,k-tmp,mid+1,r);
}
node * null(int ll,int rr)
{
    node *neww=new node();
    //node * neww=(node *)malloc(sizeof(node));
    neww->l=neww->r=NULL;
    neww->sum=0;
    if(ll==rr) return neww;
    int mid=ll+rr>>1;
    neww->l=null(ll,mid);
    neww->r=null(mid+1,rr);
    return neww;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {scanf("%d",&a[i]);hash[i]=a[i];}
    discrete();
    root[0]=null(1,n);
    for(int i=1;i<=n;i++) root[i]=build(root[i-1],1,n,hash[i]);
    int x,y,k;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&k);
        printf("%d\n",a[query(root[x-1],root[y],k,1,n)]);
    }
}

 

posted @ 2017-01-07 17:12  TRTTG  阅读(669)  评论(0编辑  收藏  举报