SPOJ1487 Query on a tree III
Description
You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels.
Input
The first line contains one integer n (1 <= n <= 10^5). The next line contains n integers li (0 <= li <= 109) which denotes the label of the i-th node. Each line of the following n - 1 lines contains two integers u, v. They denote there is an edge between node u and node v. Node 1 is the root of the tree. The next line contains one integer m (1 <= m <= 10^4) which denotes the number of the queries. Each line of the next m contains two integers x, k. (k <= the total node number in the subtree of x)
Output
For each query (x, k), output the index of the node whose label is the k-th largest in the subtree of the node x.
Sample Input
5
1 3 5 2 7
1 2
2 3
1 4
3 5
4
2 3
4 1
3 2
3 2
Sample Output
5 4 5 5
題目大意:給你一顆以1為根的樹,每個點權值各不相同,每次查詢以x為根的子樹中權值第k大的節點標號。
之前看過,一眼看上去水題,發現操作不來就沒管這道題。
今天剛好切一道樹剖題用到dfs序這個東西,那麼不就是在dfs序上求區間第k大嗎?
樹套樹/主席樹亂搞,但是卡空間,就用主席樹了。
#include<bits/stdc++.h> using namespace std; #define show_memory(x) cout<<sizeof(x)/(1024*1024.0)<<"\n"; const int Maxn=100005; struct Edge{ int cnt,h[Maxn],to[Maxn*2],next[Maxn*2]; inline void add(int x,int y){ next[++cnt]=h[x];to[cnt]=y;h[x]=cnt; } }e; #define to e.to[p] int n,m,v[Maxn]; int cnt,p[Maxn],fir[Maxn],sec[Maxn]; map<int,int>fp; void dfs(int x,int fa){ p[fir[x]=++cnt]=x; for(int p=e.h[x];p;p=e.next[p]) if(to^fa)dfs(to,x); sec[x]=cnt; } struct SegMent{ struct tree{ int ls,rs,siz; }t[Maxn*40]; int tot,root[Maxn]; inline void insert(int &x,int o,int l,int r,int val){ if(r<val||l>val)return ; t[x=++tot]=t[o]; ++t[x].siz; if(l==r)return ; int mid=l+r>>1; insert(t[x].ls,t[o].ls,l,mid,val),insert(t[x].rs,t[o].rs,mid+1,r,val); } inline int query(int R,int L,int l,int r,int kth){ if(l==r)return fp[l]; int size=t[t[R].ls].siz-t[t[L].ls].siz; int mid=l+r>>1; if(size>=kth)return query(t[R].ls,t[L].ls,l,mid,kth); else return query(t[R].rs,t[L].rs,mid+1,r,kth-size); } }seg; int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&v[i]); fp[v[i]]=i; } for(int i=1;i<n;++i){ int x,y;scanf("%d%d",&x,&y); e.add(x,y),e.add(y,x); } dfs(1,0); for(int i=1;i<=n;++i)seg.insert(seg.root[i],seg.root[i-1],0,1e9,v[p[i]]); scanf("%d",&m); for(int i=1;i<=m;++i){ int x,k;scanf("%d%d",&x,&k); printf("%d\n",seg.query(seg.root[sec[x]],seg.root[fir[x]-1],0,1e9,k)); } // show_memory(seg); return 0; }