[xdoj1216]子树第k小(dfs序+主席树)

解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题。

  1 #pragma comment(linker, "/STACK:1024000000,1024000000") `
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<cmath>
  8 #include<vector>
  9 typedef long long ll;
 10 using namespace std;
 11 const int maxn=1e5+4;
 12 int head[maxn],in[maxn],out[maxn],cnt,num;
 13 int b[maxn],va[maxn];
 14 int n,m;
 15 struct Edge{
 16     int to,nxt;
 17 }e[maxn<<2];
 18 int root[maxn];
 19 struct node{
 20     int l,r,sum;
 21 }p[maxn*22];
 22 
 23 inline int read(){
 24     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
 25     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
 26     if(k=='-')x=0-x;return x;
 27 }
 28 
 29 void add_edge(int u,int v){
 30     e[cnt].to=v;
 31     e[cnt].nxt=head[u];
 32     head[u]=cnt++;
 33 }
 34 
 35 void dfs(int u,int fa){
 36     num++;
 37     b[num]=va[u];
 38     in[u]=num;
 39     for(int i=head[u];i!=-1;i=e[i].nxt){
 40         int v=e[i].to;
 41         if(v==fa) continue;
 42         dfs(v,u);
 43     }
 44     out[u]=num;
 45 }
 46 
 47 int build(int l,int r){
 48     int rt=++cnt;
 49     p[rt].sum=0;
 50     p[rt].l=p[rt].r=0;
 51     if(l==r) return rt;
 52     int mid=(l+r)>>1;
 53     p[rt].l=build(l,mid);
 54     p[rt].r=build(mid+1,r);
 55     return rt;
 56 }
 57 
 58 int update(int l,int r,int c,int k){
 59     int nc=++cnt;
 60     p[nc]=p[c];
 61     p[nc].sum++;
 62     int mid=(l+r)>>1;
 63     if(l==r) return nc;
 64     if(mid>=k) p[nc].l=update(l,mid,p[c].l,k);
 65     else p[nc].r=update(mid+1,r,p[c].r,k);
 66     return nc;
 67 }
 68 
 69 int query(int l,int r,int x,int y,int k){
 70     if(l==r) return l;
 71     int mid=(l+r)>>1;
 72     int sum=p[p[y].l].sum-p[p[x].l].sum;
 73     if(sum>=k) return query(l,mid,p[x].l,p[y].l,k);
 74     else return query(mid+1,r,p[x].r,p[y].r,k-sum);
 75 }
 76 vector<int>v;
 77 int getid(int x){
 78     return int(lower_bound(v.begin(),v.end(),x)-v.begin())+1;
 79 }
 80 
 81 int main(){
 82     while(scanf("%d",&n)!=EOF){
 83         v.clear();
 84         memset(head,-1,sizeof head);
 85         cnt=0;
 86         num=0;
 87         for(int i=1;i<=n;i++)    va[i]=read();
 88         for(int i=0;i<n-1;i++){
 89             int t1,t2;
 90             t1=read();
 91             t2=read();
 92             add_edge(t1,t2);
 93             add_edge(t2,t1);
 94         }
 95         dfs(1,-1);
 96         for(int i=1;i<=n;i++) v.push_back(b[i]);        
 97         sort(v.begin(),v.end());
 98         v.erase(unique(v.begin(), v.end()),v.end());
 99         root[0]=build(1,n);
100         for(int i=1;i<=n;i++) root[i]=update(1,n,root[i-1],getid(b[i]));
101         int c,d;
102         m=read();
103         for(int i=0;i<m;i++){
104             c=read();
105             d=read();
106             int ans=query(1,n,root[in[c]-1],root[out[c]],d);
107             printf("%d
",v[ans-1]);
108         }
109     }
110     return 0;
111 }
原文地址:https://www.cnblogs.com/elpsycongroo/p/7430053.html