bzoj1803: Spoj1487 Query on a tree III

来源:互联网 发布:vb 判断文件是否存在 编辑:程序博客网 时间:2024/06/05 08:37

传送门
显然看到子树九要想到dfs序。
按照dfs序建立主席树。
然后就在树上贪心往右走就可以了。

#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define N 100005using namespace std;struct edge{int to,next;}e[N*2];int head[N],pos[N],mx[N],rt[N],val[N],fa[N];int cnt,tot,sz,n,Q,x,y;int ls[N*32],rs[N*32],sum[N*32],fl[N*32];void add(int x,int y){    e[++tot]=(edge){y,head[x]};    head[x]=tot;}void add(int x,int &nx,int l,int r,int v,int id){    nx=++sz; sum[nx]=sum[x]+1;    ls[nx]=ls[x]; rs[nx]=rs[x];    if (l==r){        fl[nx]=id;        return;    }    int mid=(l+r)/2;    if (v<=mid) add(ls[x],ls[nx],l,mid,v,id);    else add(rs[x],rs[nx],mid+1,r,v,id);}void solve(int x,int y,int l,int r,int rk){    if (l==r){        printf("%d\n",fl[y]);        return;    }    int mid=(l+r)/2;    if (sum[ls[y]]-sum[ls[x]]>=rk) solve(ls[x],ls[y],l,mid,rk);    else solve(rs[x],rs[y],mid+1,r,rk-sum[ls[y]]+sum[ls[x]]);}void dfs(int x){    pos[x]=++cnt;    add(rt[cnt-1],rt[cnt],1,1e9,val[x],x);    for (int i=head[x];i;i=e[i].next)        if (e[i].to!=fa[x])            fa[e[i].to]=x,dfs(e[i].to);    mx[x]=cnt;}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&val[i]);    for (int i=1;i<n;i++){        scanf("%d%d",&x,&y);        add(x,y); add(y,x);    }    dfs(1);    scanf("%d",&Q);    while (Q--){        scanf("%d%d",&x,&y);        solve(rt[pos[x]-1],rt[mx[x]],1,1e9,y);    }}