BZOJ1803Spoj1487 Query on a tree III——主席树

题目大意

  给一棵有点权的n个点的有根树,保证任意两点的点权不同,m次询问每次询问x的子树中权值第k大的点。

输入

  先输入n,然后每个点点权,再输入n-1行每行两个数x,y代表x和y相连,再输入m,之后m次询问,每行两个数x,k。

 

  主席树,随便找一个点为根,再dfs出树的dfs序,按dfs序建每一时刻主席树,利用主席树查询x子树区间第k大。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char _read()
{
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    int x=0,f=1;char ch=_read();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=_read();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=_read();}
    return x*f;
}
int n,m;
int x,y;
int tot;
int num;
int cnt;
int q[100010];
int s[100010];
int t[100010];
int v[100010];
int to[200010];
int ls[4000010];
int rs[4000010];
int next[200010];
int head[100010];
int root[100010];
int sum[4000010];
map<int,int>b;
void add(int x,int y)
{
    tot++;
    next[tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}
void dfs(int x,int fa)
{
    s[x]=++num;
    q[num]=x;
    for(int i=head[x];i;i=next[i])
    {
        if(to[i]!=fa)
        {
            dfs(to[i],x);
        }
    }
    t[x]=num;
}
int updata(int pre,int l,int r,int v)
{
    int rt=++cnt;
    if(l==r)
    {
        sum[rt]=sum[pre]+1;
        return rt;
    }
    ls[rt]=ls[pre];
    rs[rt]=rs[pre];
    sum[rt]=sum[pre]+1;
    int mid=(l+r)>>1;
    if(v<=mid)
    {
        ls[rt]=updata(ls[pre],l,mid,v);
    }
    else
    {
        rs[rt]=updata(rs[pre],mid+1,r,v);
    }
    return rt;
}
int query(int x,int y,int l,int r,int k)
{
    if(l==r)
    {
        return b[l];
    }
    int val=sum[ls[y]]-sum[ls[x]];
    int mid=(l+r)>>1;
    if(val<k)
    {
        return query(rs[x],rs[y],mid+1,r,k-val);
    }
    else
    {
        return query(ls[x],ls[y],l,mid,k);
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        v[i]=read();
        b[v[i]]=i;
    }
    for(int i=1;i<n;i++)
    {
        x=read();
        y=read();
        add(x,y);
        add(y,x);
    }
    dfs(1,0);
    for(int i=1;i<=num;i++)
    {
        root[i]=updata(root[i-1],0,1e9,v[q[i]]);
    }
    m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();
        y=read();
        printf("%d\n",query(root[s[x]-1],root[t[x]],0,1e9,y));
    }
}
posted @ 2018-08-09 16:28  The_Virtuoso  阅读(206)  评论(0编辑  收藏  举报