你被給定一棵帶點權的n個點的有根數,點從1到n編號。node
定義查詢 query(x,k): 尋找以x爲根的k大點的編號(從小到大排序第k個點)c++
假設沒有兩個相同的點權。數組
輸入格式: 第一行爲整數n,第二行爲點權,接下來n-1行爲樹邊,接下來一行爲整數m,下面m行爲兩個整數x,k,表明query(x,k)ui
輸出格式: m行,輸出每次查詢的結果。spa
Translated by @vegacx翻譯
You are given a node-labeled rooted tree with n nodes.rest
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.code
輸入格式:排序
The first line contains one integer n (1 <= n <= 10 ^{5}5 ). The next line contains n integers l {i}i_ (0 <= l {i}i_ <= 10 ^{9}9 ) which denotes the label of the i-th node.get
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}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)
輸出格式:
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.
輸入樣例#1:
5
1 3 5 2 7
1 2
2 3
1 4
3 5
4
2 3
4 1
3 2
3 2
輸出樣例#1:
5
4
5
5
傳送門
樹上靜態主席樹...
顯然咱們要根據dfs序來創建主席樹,也正因如此,因此咱們在dfs的過程當中要從新賦一下值,給當前dfs序爲i的節點另開兩個存值的數組,一個是原數組,一個離散數組,這樣值才能與主席樹對上號
void dfs(int u,int fa) { id[u]=++cnt, a[cnt]=b[cnt]=w[u], inv[cnt]=u, size[u]=1;//inv[]存的是經過dfs序找到節點 for (int i=head[u];i;i=nex[i]) { if (to[i]==fa) continue; dfs(to[i],u); size[u]+=size[to[i]]; } }
在加入節點的過程當中,由於題目問的是節點編號而不是值,咱們還要把當前值賦爲節點編號
至於查詢,就是以dfs序和子樹大小來查,由於是連續的...
其實若是會靜態主席樹,這道題稍微難一點的主要仍是建樹,會建樹就會查詢了
#include<bits/stdc++.h> #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define rg register #define mid ((l+r)>>1) #define in(i) (i=read()) using namespace std; const int N=1e5+10; int read() { int ans=0,f=1; char i=getchar(); while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();} while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar(); return ans*=f; } int T,n,m,tot,cur,cnt; int w[N],a[N],b[N],id[N],inv[N],size[N],ans[N]; int to[N<<1],nex[N<<1],head[N]; int rt[N<<5],lc[N<<5],rc[N<<5],sum[N<<5]; void add(int a,int b) { to[++cur]=b,nex[cur]=head[a],head[a]=cur; to[++cur]=a,nex[cur]=head[b],head[b]=cur; } void build(int &u,int l,int r) { u=++tot,sum[u]=0; if (l==r) return; build(lc[u],l,mid); build(rc[u],mid+1,r); } void update(int &u,int l,int r,int pre,int x) { u=++tot; sum[u]=sum[pre]+1,lc[u]=lc[pre],rc[u]=rc[pre]; if (l==r) return; if(x<=mid) update(lc[u],l,mid,lc[pre],x); else update(rc[u],mid+1,r,rc[pre],x); } int query(int u,int v,int l,int r,int k) { if(l==r) return ans[l]; int rest=sum[lc[v]]-sum[lc[u]]; if(k<=rest) return query(lc[u],lc[v],l,mid,k); else return query(rc[u],rc[v],mid+1,r,k-rest); } void dfs(int u,int fa) { id[u]=++cnt, a[cnt]=b[cnt]=w[u], inv[cnt]=u, size[u]=1; for (int i=head[u];i;i=nex[i]) { if (to[i]==fa) continue; dfs(to[i],u); size[u]+=size[to[i]]; } } int main() { in(n); for (int i=1;i<=n;i++) in(w[i]); for (int i=1,x,y;i<n;i++) in(x), in(y), add(x,y); dfs(1,0); sort(b+1,b+1+n); build(rt[0],1,n); for (int i=1;i<=n;i++) { a[i]=lower_bound(b+1,b+1+n,a[i])-b; ans[a[i]]=inv[i]; update(rt[i],1,n,rt[i-1],a[i]); } in(m); for (int i=1,x,k;i<=m;i++) { in(x), in(k); printf("%d\n",query(rt[id[x]-1],rt[id[x]+size[x]-1],1,n,k)); } }