题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4366
Successor
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2961 Accepted Submission(s): 689
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
题意:(转)
某公司有 n 个人,编号从 0 到 n-1 ,0号是BOSS。除BOSS外,每个人有忠诚度和能力两个属性,每个人的忠诚度都不同。每个人都有可能被BOSS炒鱿鱼,当某个人被炒后,他的所有下级中能力大于他且具有最大忠诚度的人将取代他的位置。现在给定所有人的上下级关系(下级的编号总是比上级大)和一些被炒鱿鱼的人的编号,输出取代被炒人的人的编号,如果没人取代被炒人,输出“-1”。
PS:首先,把以每个节点为根的子树转化为连续区间以便于处理。然后,按能力值由大到小对员工进行排序,能力值相同时,编号小的排在前面。最后,从左到右求以某个人为根的子树中忠诚度最大的人的编号,然后将根的忠诚度插入到线段树中。
因为每个忠诚值必然对应一个唯一的序号,那么开个 map映射一下好了。
DFS时间戳,记录进入结点的时间戳和出结点的时间戳,两个时间戳之间的都是这个结点的子孙结点了。
代码如下:
#pragma comment(linker,"/STACK:102400000,102400000") //手动扩栈 #include <cstdio> #include <cstring> #include <map> #include <vector> #include <algorithm> using namespace std; #define lson l , mid , rt << 1 #define rson mid + 1 , r , rt << 1 | 1 const int maxn = 50017; int n, m; int Max[maxn << 2], ans[maxn]; int L[maxn], R[maxn], idx; int vis[maxn]; map<int, int> mm; vector<int> v[maxn]; struct Staff { int b, c; int id; } s[maxn]; bool cmp(Staff s1, Staff s2) { if(s1.c == s2.c) { return s1.id < s2.id; } return s1.c > s2.c; } void PushUP(int rt) //把当前结点的信息更新到父结点 { Max[rt] = max(Max[rt<<1],Max[rt<<1|1]); } void build(int l, int r, int rt) { if(l == r) { Max[rt] = -1; return ; } int mid = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int p, int c, int l, int r, int rt) { if(l == r) { Max[rt] = c; return ; } int mid = (l + r) >> 1; if(p <= mid) { update(p , c , lson); } else { update(p , c , rson); } PushUP(rt); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return Max[rt]; } int mid = (l + r) >> 1; int ret = -999; if(L <= mid) { ret = max(ret, query(L , R , lson)); } if(R > mid) { ret = max(ret, query(L , R , rson)); } return ret; } void dfs(int x) { L[x] = idx; vis[x] = 1; int num = v[x].size(); for(int i = 0; i < num; i++) { if(!vis[v[x][i]]) { idx++; int tt = v[x][i]; dfs(tt); } } R[x] = idx; } void init() { memset(vis, 0, sizeof(vis)); for(int i = 0; i < maxn; i++) { v[i].clear(); } mm.clear(); } int main() { int t; scanf("%d",&t); while(t--) { init(); scanf("%d%d",&n, &m); int a, b, c; for(int i = 1; i <= n-1; i++) { scanf("%d%d%d", &a, &b, &c); v[a].push_back(i); s[i].b = b; s[i].c = c; s[i].id = i; mm[b] = i; } mm[-1] = -1; sort(s+1, s+n, cmp);//从大到小 build(1, n-1, 1); idx = 0; //DFS时间戳,记录进入结点的时间戳和出结点的时间戳, //两个时间戳之间的都是这个结点的子孙结点了 dfs(0); for(int i = 1; i <= n-1; i++) { int ret = query(L[s[i].id], R[s[i].id], 1, n-1, 1); ans[s[i].id] = mm[ret]; update(L[s[i].id], s[i].b, 1, n-1, 1); } int k; for(int i = 0; i < m; i++) { scanf("%d",&k); printf("%d\n",ans[k]); } } return 0; } /* 9 5 3 0 100 99 1 80 100 1 102 150 3 90 50 1 2 3 5 3 0 100 99 1 80 100 2 102 150 3 90 50 1 2 3 */
版权声明:本文为博主原创文章,未经博主允许不得转载。