S u c c e s s o r Successor Successor
Time Limit: 2000/1000 MS (Java/Others) | Memory Limit: 65536/65536 K (Java/Others) |
---|---|
Total Submission(s): 6041 | Accepted Submission(s): 1486 |
Problem Description
Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty and ability.Some times Sean will fire one staff.Then one of the fired man’s Subordinates will replace him whose ability is higher than him and has the highest loyalty for company.Sean want to know who will replace the fired man.
Input
In the first line a number T indicate the number of test cases. Then for each case the first line contain 2 numbers n,m (2<=n,m<=50000),indicate the company has n person include Sean ,m is the times of Sean’s query.Staffs are numbered from 1 to n-1,Sean’s number is 0.Follow n-1 lines,the i-th(1<=i<=n-1) line contains 3 integers a,b,c(0<=a<=n-1,0<=b,c<=1000000),indicate the i-th staff’s superior Serial number,i-th staff’s loyalty and ability.Every staff ‘s Serial number is bigger than his superior,Each staff has different loyalty.then follows m lines of queries.Each line only a number indicate the Serial number of whom should be fired.
Output
For every query print a number:the Serial number of whom would replace the losing job man,If there has no one to replace him,print -1.
Sample Input
1
3 2
0 100 99
1 101 100
1
2
Sample Output
2
-1
Author
FZU
Source
2012 Multi-University Training Contest 7
题意:
给出一棵表示上下级关系的树,每个节点(除了根节点之外)都有一个Loyalty值和Ability值,给出m个询问,每次要求计算出节点P的子树中,Ability值大于节点P的节点并且Loyalty值最大的那个节点。
TJ:
要求Loyalty最大的值,可以用线段树来维护区间Loyalty的最大值,但是维护的区间边界是什么,题目给出的是一棵关系树,对于DFS来说,子树的遍历顺序肯定在当前节点之后,给每个节点两个顺序编号,分别是遍历进入以该节点为根的树的DFS遍历序号和出该节点的遍历序号,就可以得到一个线性序列,之后只要维护这个线性序列的Loyalty的最大值就好了。
但是题目给出了另一个约束条件,就是子节点的Ability值必须要大于当前节点,对于这个要求,可以先把所有点按各点的Ability值从大到小进行排序,然后按顺序把各个节点的Loyalty值更新到线段树中去,按这样的顺序,每次查询的时候,有Loyalty值的点的Ability值肯定大于当前需要查询的点(注意Ability值相同的点要同时查询再更新),这样就可以把每个点的答案都记录下来(记录下来的是一个Loyalty值),由于每个Loyalty值都是不一样的,所以可以把Loyalty值和节点的标号一一映射起来,要查询的节点标号就可以通过map把Loyalty值转换过去了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 5e4+7;
map<int,int> mp;
int T,n,m,head[maxn],edge_num,in[maxn],out[maxn],number,res[maxn];
struct EDGE{
int to,next;
}edge[maxn];
struct EMP{
int id,loyal,ability;
bool operator < (const EMP &x){
return ability>x.ability;
}
}emp[maxn];
struct Segment_Tree{
int maxx[maxn<<2];
void push_up(int rt){
maxx[rt] = max(maxx[rt<<1],maxx[(rt<<1)+1]);
}
void update(int l,int r,int pos,int rt,int val){
if(l+1==r){
maxx[rt] = val;
return;
}
int mid = (l+r)>>1;
if(pos<mid) update(l,mid,pos,rt<<1,val);
else update(mid,r,pos,(rt<<1)+1,val);
push_up(rt);
}
int query(int l,int r,int ql,int qr,int rt){
if(ql<=l && r<=qr) return maxx[rt];
if(l>=qr || ql>=r) return -1;
int mid = (l+r)>>1;
return max(query(l,mid,ql,qr,rt<<1),query(mid,r,ql,qr,(rt<<1)+1));
}
}Seg_Tree;
void init(){
memset(Seg_Tree.maxx,255,sizeof(Seg_Tree.maxx));
mp.clear(); mp.insert(pair<int,int>(-1,-1));
memset(head,255,sizeof(head));
edge_num = 0;
}
void add_edge(int u,int v){
edge[edge_num].to = v;
edge[edge_num].next = head[u];
head[u] = edge_num++;
}
void dfs(int now){
in[now] = number++;
for(int i=head[now];i!=-1;i=edge[i].next) dfs(edge[i].to);
out[now] = number;
}
void pre_done(){
number = 0;
dfs(0);
sort(emp+1,emp+n);
for(int i=1,now=1;i<n;i++){
int id = emp[i].id;
res[id] = mp[Seg_Tree.query(1,number,in[id],out[id],1)];
if(i!=n-1&&emp[i+1].ability==emp[i].ability) continue;
for(;now!=i+1;now++){
int nid = emp[now].id;
Seg_Tree.update(1,number,in[nid],1,emp[now].loyal);
}
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
init();
for(int i=1;i<n;i++){
int pre;
scanf("%d %d %d",&pre,&emp[i].loyal,&emp[i].ability);
add_edge(pre,i);
mp.insert(pair<int,int>(emp[i].loyal,i));
emp[i].id = i;
}
pre_done();
for(int i=1;i<=m;i++){
int pos;
scanf("%d",&pos);
printf("%d\n",res[pos]);
}
}
return 0;
}