hdu 4366 Successor
http://acm.hdu.edu.cn/showproblem.php?pid=4366
线段树
题意是要找某个点其子孙中能力值其能力值的中忠诚度最大的。
首先可以遍历一遍将树上每个点标记为一维区间上的某个点,且在同一棵子树内的点是连续的一段。将所有点按能力从大到小排序,能力相同的编号小的排在前面,然后扫描一遍,扫描时维护一颗线段树,先查找该点为根节点的子树内的最优值,然后插入该点的忠诚度。维护区间的最大忠诚值就行了。

1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<iostream> 5 #include<utility> 6 using namespace std; 7 const int maxn = 50010; 8 const int N = 1000005; 9 struct nd{ 10 int v,next; 11 }edge[maxn]; 12 int p[maxn],ls[maxn][2],lo[maxn],Hash[N],ab[maxn],id[maxn]; 13 int as[maxn<<2],ans[maxn]; 14 int n,m,ecnt,idx; 15 void add(int u,int v) 16 { 17 edge[ecnt].v = v; 18 edge[ecnt].next = p[u]; 19 p[u] = ecnt++; 20 } 21 bool cmp(int a,int b) 22 { 23 if(ab[a]^ab[b])return ab[a] > ab[b]; 24 return a < b; 25 } 26 void getlist(int x) 27 { 28 ls[x][0] = idx++; 29 for(int i = p[x]; ~i; i = edge[i].next) 30 getlist(edge[i].v); 31 ls[x][1] = idx - 1; 32 } 33 void readin() 34 { 35 int i,a; 36 scanf("%d %d",&n,&m); 37 ecnt = 0; 38 memset(p,-1,sizeof(p)); 39 for(i = 1; i < n; ++ i){ 40 scanf("%d %d %d",&a,lo+i,ab+i); 41 id[i] = i; 42 Hash[lo[i]] = i; 43 add(a,i); 44 } 45 idx = 0; 46 sort(id+1,id+n,cmp); 47 getlist(0); 48 } 49 void update(int rt,int l,int r,int L,int val) 50 { 51 int mid = (l + r) >> 1; 52 if(l==r){ 53 as[rt] = val; 54 return; 55 } 56 if(L<=mid)update(rt<<1,l,mid,L,val); 57 else update(rt<<1|1,mid+1,r,L,val); 58 as[rt] = max(as[rt<<1],as[rt<<1|1]); 59 } 60 int ret; 61 void query(int rt,int l,int r,int L,int R) 62 { 63 int mid = (l + r) >> 1; 64 if(L<=l && r<= R){ 65 ret = max(ret,as[rt]); 66 return; 67 } 68 if(L<=mid)query(rt<<1,l,mid,L,R); 69 if(R>mid)query(rt<<1|1,mid+1,r,L,R); 70 } 71 void processing() 72 { 73 memset(as,-1,sizeof(as)); 74 for(int i = 1; i < n; ++ i){ 75 ret = -1; 76 if(ls[id[i]][0]^ls[id[i]][1]) 77 query(1,1,n,ls[id[i]][0],ls[id[i]][1]); 78 if(~ret)ans[id[i]] = Hash[ret]; 79 else ans[id[i]] = -1; 80 update(1,1,n,ls[id[i]][0],lo[id[i]]); 81 } 82 while(m--){ 83 scanf("%d",&idx); 84 printf("%d\n",ans[idx]); 85 } 86 } 87 int main() 88 { 89 int T; 90 for(scanf("%d",&T);T--;){ 91 readin(); 92 processing(); 93 }return 0; 94 }