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

  题目大意 给定一棵树,每个点有两个权值,忠诚度和能力值,每次询问点x的子树中能力值大于它,忠诚度最高的一位的编号。

Solution 1 树分块

  因为查询的时候,查询一个节点的子树实际上是等于查询一段区间内的数据,所以考虑对dfs序进行分块。

  按照dfs序进行分块,块内按忠诚度进行排序,再记录后缀忠诚度最大值。

  根据常用套路,每次查询,对于块两端部分,暴力for。中间每个块lower_bound upper_bound一下查询合法的一段,然后用后缀忠诚度最大值进行更新答案就好了。

  (这是我比较笨的分块方法)

  设块的大小为s,块的数量为c,则总时间复杂度为hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

Code

  1 /**
  2  * hdu
  3  * Problem#4366
  4  * Accepted
  5  * Time: 748ms
  6  * Memory: 8468k 
  7  */
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 typedef bool boolean;
 11 
 12 typedef class Staff {
 13     public:
 14         int loy;
 15         int abi;
 16         int id;
 17         
 18         boolean operator < (Staff b) const {
 19             if(abi != b.abi)    return abi < b.abi;
 20             return loy < b.loy;
 21         }
 22 }Staff;
 23 
 24 boolean operator < (const int& x, const Staff& s) {
 25     return x < s.abi;
 26 }
 27 
 28 const int maxcsize = 300;
 29 typedef class Chunk {
 30     public:
 31         int len;
 32         Staff sta[maxcsize];
 33         int maxv[maxcsize];
 34         int ans[maxcsize];
 35         
 36         void init(Staff* lis, int from, int end) {
 37             len = end - from;
 38             for(int i = from; i < end; i++)
 39                 sta[i - from] = lis[i];
 40             sort(sta, sta + len);
 41             maxv[len] = -1;
 42             ans[len] = -1;
 43             for(int i = len - 1; i >= 0; i--) {
 44                 if(sta[i].loy > maxv[i + 1])
 45                     maxv[i] = sta[i].loy, ans[i] = sta[i].id;
 46                 else
 47                     maxv[i] = maxv[i + 1], ans[i] = ans[i + 1];
 48             }    
 49         }
 50         
 51         void getAns(int limit, int& rmaxv, int& rans) {
 52             int pos = upper_bound(sta, sta + len, limit) - sta;
 53             if(maxv[pos] > rmaxv)
 54                 rmaxv = maxv[pos], rans = ans[pos];
 55         }
 56 }Chunk;
 57 
 58 int n, m;
 59 int cs, cc;
 60 vector<int> *g;
 61 Staff lis[50005];
 62 Staff *nlis;
 63 Chunk chs[300];
 64 
 65 inline void init() {
 66     scanf("%d%d", &n, &m);
 67     g = new vector<int>[(n + 1)];
 68     nlis = new Staff[(n + 1)];
 69     for(int i = 1, x; i < n; i++) {
 70         scanf("%d%d%d", &x, &lis[i].loy, &lis[i].abi);
 71         lis[i].id = i;
 72         g[x].push_back(i);
 73     }
 74     lis[0].loy = lis[0].abi = 23333333;
 75     lis[0].id = 0;
 76     cs = sqrt(n + 0.5);
 77 }
 78 
 79 int cnt;
 80 int visitID[50005], exitID[50005];
 81 int visit[50005];
 82 inline void dfs(int node) {
 83     visitID[node] = ++cnt;
 84     visit[cnt] = node;
 85     for(int i = 0; i < (signed)g[node].size(); i++)
 86         dfs(g[node][i]);
 87     exitID[node] = cnt;
 88 }
 89 
 90 inline void init_chunks() {
 91     for(int i = 1; i <= n; i++)
 92         nlis[i] = lis[visit[i]], nlis[i].id = i;
 93     for(cc = 0; cc * cs < n; cc++)
 94         chs[cc + 1].init(nlis, cc * cs + 1, min((cc + 1) * cs, n) + 1);
 95 }
 96 
 97 inline void solve() {
 98     int l, r, x, maxv, ans, lim;
 99     while(m--) {
100         scanf("%d", &x);
101         maxv = -1, ans = -1;
102         l = visitID[x], r = exitID[x], lim = lis[x].abi;
103         int lid = l / cs + 1, rid = r / cs + 1;
104         if(lid == rid) {
105             for(int i = l; i <= r; i++)
106                 if(nlis[i].abi > lim && nlis[i].loy > maxv)
107                     maxv = nlis[i].loy, ans = i;
108         } else {
109 //            if(x == 992)
110 //                putchar('a');
111             for(int i = l; i <= lid * cs; i++)
112                 if(nlis[i].abi > lim && nlis[i].loy > maxv)
113                     maxv = nlis[i].loy, ans = i;
114             for(int i = (rid - 1) * cs + 1; i <= r; i++)
115                 if(nlis[i].abi > lim && nlis[i].loy > maxv)
116                     maxv = nlis[i].loy, ans = i;
117             for(int i = lid + 1; i < rid; i++)
118                 chs[i].getAns(lim, maxv, ans);
119         }
120         printf("%d\n", (ans == -1) ? (-1) : (visit[ans]));
121     }
122 }
123 
124 inline void clear() {
125     delete[] g;
126     delete[] nlis;
127 }
128 
129 int T;
130 int main() {
131 //    freopen("a.in", "r", stdin);
132 //    freopen("a.out", "w", stdout); 
133     scanf("%d", &T);
134     while(T--) {
135         init();
136         cnt = 0;
137         dfs(0);
138         init_chunks();
139         solve();
140         clear();
141     }
142 //    fprintf(stderr, "Time: %dms\n", clock());
143     return 0;
144 }
Successor(Tree Division)

相关文章: