Now we have a tree and some queries to deal with. Every node in the tree has a value on it. For one node A, we want to know the largest three values in all the nodes of the subtree whose root is node A. Node 0 is root of the tree, except it, all other nodes have a parent node.
Input
There are several test cases. Each test case begins with a line contains one integer n(1 ≤ n ≤ 10000), which indicates the number of the node in the tree. The second line contains one integer v[0], the value on the root. Then for the following n - 1 lines(from the 3rd line to the (n + 1)th line), let i + 2 be the line number, then line i + 2 contains two integers parent and v[i], here parent is node i's parent node, v[i] is the value on node i. Here 0 ≤ v[i] ≤ 1000000. Then the next line contains an integer m(1 ≤ m ≤ 10000), which indicates the number of queries. Following m lines, each line contains one integer q, 0 ≤ q < n, it meas a query on node q.
Output
For each test case, output m lines, each line contains one or three integers. If the query asked for a node that has less than three nodes in the subtree, output a "-1"; otherwise, output the largest three values in the subtree, from larger to smaller.
Sample Input
5 1 0 10 0 5 2 7 2 8 5 0 1 2 3 4
Sample Output
10 8 7 -1 8 7 5 -1 -1
题意:给一颗树,每个结点都有一个权值,问某一点及其子树中,最大的三个数
思路:其实根已经确定了,直接深搜就行了,其实连建树都不用。而我刚看到的时候一直想着怎么建树,想着想着就写成线段树了。因为一开始就想到zoj3686,但是一直想不起来当时是怎么建树的,然后找了一下源代码,下面的dfs代码,就是把当前结点放在左端,然后通过递归回来的最后一个结点放在右端。然后判断一个结点是否满足三个数以上只须判断他的左右间距是否大于3,然后查找就是线段树查找了
void add(int s,int e){
E[ind].e=e;
E[ind].next=head[s];
head[s]=ind++;
}
void dfs(int s){
l[s]=++p;
for(int now=head[s];now!=-1;now=E[now].next){
dfs(E[now].e);
}
r[s]=p;
}
#include<cstdio>
#include<cstring>
#include<stdlib.h>
using namespace std;
#define SIZE 10005
#define lson rt<<1
#define rson rt<<1|1
int head[SIZE],l[SIZE],r[SIZE],w[SIZE],ind,p,tp;
int val[SIZE],cou[SIZE];
struct tree{
int l,r,sum;
int num[7];
}T[SIZE<<2];
struct edge{
int e,next;
}E[SIZE];
int cmp(const void *a,const void *b){
return *(int *)b-*(int *)a;
}
void add(int s,int e){
E[ind].e=e;
E[ind].next=head[s];
head[s]=ind++;
}
void dfs(int s){
l[s]=++p;
for(int now=head[s];now!=-1;now=E[now].next){
dfs(E[now].e);
}
r[s]=p;
}
void pushup(int rt){
int sum=T[lson].sum+T[rson].sum;
T[rt].sum=(sum>6?6:sum);
int top=0;
for(int i=0;i<T[lson].sum&&i<3;i++)
T[rt].num[top++]=T[lson].num[i];
for(int i=0;i<T[lson].sum&&i<3;i++)
T[rt].num[top++]=T[rson].num[i];
qsort(T[rt].num,top,sizeof(T[rt].num[0]),cmp);
}
void built(int l,int r,int rt){
T[rt].l=l;
T[rt].r=r;
T[rt].sum=0;
if(l==r) {
T[rt].sum=1;
T[rt].num[0]=val[l];
return;
}
int mid=(l+r)>>1;
built(l,mid,lson);
built(mid+1,r,rson);
pushup(rt);
}
void query(int l,int r,int rt){
if(l<=T[rt].l&&T[rt].r<=r){
for(int i=0;i<T[rt].sum&&i<3;i++)
cou[tp++]=T[rt].num[i];
return;
}
int mid=(T[rt].l+T[rt].r)>>1;
if(l<=mid)
query(l,r,lson);
if(r>mid)
query(l,r,rson);
}
int main(void){
int n,pre;
int m;
while(~scanf("%d",&n)){
memset(head,-1,sizeof(head));
ind=p=0;
scanf("%d",&w[0]);
for(int i=1;i<n;i++){
scanf("%d%d",&pre,&w[i]);
add(pre,i);
}
dfs(0);
for(int i=0;i<n;i++)
val[l[i]]=w[i];
built(l[0],r[0],1);
scanf("%d",&m);
while(m--){
scanf("%d",&pre);
if(r[pre]-l[pre]+1<3){
printf("-1\n");
continue;
}
tp=0;
query(l[pre],r[pre],1);
qsort(cou,tp,sizeof(cou[0]),cmp);
printf("%d %d %d\n",cou[0],cou[1],cou[2]);
}
}
return 0;
}