HDU5840(SummerTrainingDay08-B 树链剖分+分块)
This world need more Zhu
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 454 Accepted Submission(s): 84
Problem Description
As we all know, Zhu is the most powerful man. He has the infinite power to protest the world. We need more men like Zhu!
In Duoladuo, this place is like a tree. There are n vertices and n−1 edges. And the root is 1. Each vertex can reached by any other vertices. Each vertex has a people with value Ai named Zhu's believer.
Liao is a curious baby, he has m questions to ask Zhu. But now Zhu is busy, he wants you to help him answer Liao's questions.
Liao's question will be like "u v k".
That means Liao want to know the answer from following code:
ans = 0; cnt = 0;
for x in the shortest path from u to v {
cnt++;
if(cnt mod k == 0) ans = max(ans,a[x]);
}
print(ans).
Please read the hints for more details.
In Duoladuo, this place is like a tree. There are n vertices and n−1 edges. And the root is 1. Each vertex can reached by any other vertices. Each vertex has a people with value Ai named Zhu's believer.
Liao is a curious baby, he has m questions to ask Zhu. But now Zhu is busy, he wants you to help him answer Liao's questions.
Liao's question will be like "u v k".
That means Liao want to know the answer from following code:
ans = 0; cnt = 0;
for x in the shortest path from u to v {
cnt++;
if(cnt mod k == 0) ans = max(ans,a[x]);
}
print(ans).
Please read the hints for more details.
Input
In the first line contains a single positive integer T, indicating number of test case.
In the second line there are two numbers n, m. n is the size of Duoladuo, m is the number of Liao's questions.
The next line contains n integers A1,A2,...An, means the value of ith vertex.
In the next n−1 line contains tow numbers u, v. It means there is an edge between vertex u and vertex v.
The next m lines will be the Liao's question:
u v k
1≤T≤10,1≤n≤100000,1≤m≤100000,1≤u,v≤n,1≤k, Ai≤1000000000.
In the second line there are two numbers n, m. n is the size of Duoladuo, m is the number of Liao's questions.
The next line contains n integers A1,A2,...An, means the value of ith vertex.
In the next n−1 line contains tow numbers u, v. It means there is an edge between vertex u and vertex v.
The next m lines will be the Liao's question:
u v k
1≤T≤10,1≤n≤100000,1≤m≤100000,1≤u,v≤n,1≤k, Ai≤1000000000.
Output
For each case, output Case #i: (i is the number of the test case, from 1 to T).
Then, you need to output the answer for every Liao's questions.
Then, you need to output the answer for every Liao's questions.
Sample Input
1
5 5
1 2 4 1 2
1 2
2 3
3 4
4 5
1 1 1
1 3 2
1 3 100
1 5 2
1 3 1
Sample Output
Case #1:
1
2
0
2
4
Hint
In query 1,there are only one vertex in the path,so the answer is 1. In query 2,there are three vertices in the path.But only the vertex 2 mod 2 equals to 0. In query 3,there are three vertices in the path.But no vertices mod 100 equal to 0. In query 4,there are five vertices in the path.There are two vertices mod 2 equal to 0.So the answer is max(a[2],a[4]) = 2. In query 5,there are three vertices in the path.And all the vertices mod 1 equal to 0. So the answer is a[3] = 4.
Author
UESTC
Source
1 //2017-08-08 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <vector> 7 #define lson (id<<1) 8 #define rson ((id<<1)|1) 9 10 using namespace std; 11 12 const int N = 100010; 13 const int LEN = 20;//块的大小 14 vector<int> G[N]; 15 int n, m, label, answer[N]; 16 17 //树链剖分 18 int arr[N];//arr[i]表示节点i的权值 19 int fa[N];//fa[i]表示节点i的父亲 20 int son[N];//son[i]表示节点i的重儿子 21 int top[N];//top[i]表示节点i所在重链的顶端节点 22 int size[N];//size[i]表示以节点i为根的子树的节点数 23 int deep[N];//deep[i]表示节点i的深度 24 int postion[N];//postion[i]表示节点i在线段树中的位置 25 int trID[N];//trID[i]表示节点i在剖分后的新编号 26 27 void dfs1(int u, int father){ 28 fa[u] = father; 29 son[u] = 0; 30 size[u] = 1; 31 for(auto v: G[u]){ 32 if(v == father)continue; 33 deep[v] = deep[u]+1; 34 dfs1(v, u); 35 size[u] += size[v]; 36 if(size[v] > size[son[u]]) 37 son[u] = v; 38 } 39 } 40 41 void dfs2(int u, int ancestor){ 42 top[u] = ancestor; 43 postion[u] = ++label; 44 trID[label] = u; 45 if(son[u]) 46 dfs2(son[u], ancestor); 47 for(auto v: G[u]){ 48 if(v == fa[u] || v == son[u]) 49 continue; 50 dfs2(v, v); 51 } 52 } 53 54 //最近公共祖先 55 inline int lca(int u, int v){ 56 while(top[u] ^ top[v]){ 57 if(deep[top[u]] < deep[top[v]]) 58 swap(u, v); 59 u = fa[top[u]]; 60 } 61 return deep[u] < deep[v] ? u : v; 62 } 63 64 //线段树 65 struct Node{ 66 int l, r, v; 67 }tree[N<<2]; 68 int nS[N], qL[N], qR[N]; 69 70 void build(int id, int l , int r){ 71 tree[id].l = l; 72 tree[id].r = r; 73 if(l == r){ 74 tree[id].v = arr[trID[nS[l]]]; 75 return; 76 } 77 int mid = (l+r)>>1; 78 build(lson, l, mid); 79 build(rson, mid+1, r); 80 tree[id].v = max(tree[lson].v, tree[rson].v); 81 } 82 83 int query(int id, int l, int r){ 84 if(tree[id].l == l && tree[id].r == r) 85 return tree[id].v; 86 int mid = (tree[id].l+tree[id].r)>>1; 87 if(l > mid)return query(rson, l, r); 88 if(r <= mid)return query(lson, l, r); 89 return max(query(lson, l, mid), query(rson, mid+1, r)); 90 } 91 92 inline int cal(int l, int r, int k){ 93 if(qL[k] > qR[k])return 0; 94 l = lower_bound(nS+qL[k], nS+qR[k]+1, l)-nS; 95 r = upper_bound(nS+qL[k], nS+qR[k]+1, r)-nS-1; 96 if(l <= r)return query(1, l, r); 97 else return 0; 98 } 99 100 int question(int u, int v, int k){ 101 int ans = -1, f = lca(u, v); 102 int uk = (deep[u] + 1)%k; 103 int vk = (deep[f] + (k - (deep[u]-deep[f]+1)%k)) % k; 104 while(top[u] ^ top[v]){ 105 if(deep[top[u]] > deep[top[v]]){ 106 ans = max(ans, cal(postion[top[u]], postion[u], uk)); 107 u = fa[top[u]]; 108 }else{ 109 ans = max(ans, cal(postion[top[v]], postion[v], vk)); 110 v = fa[top[v]]; 111 } 112 } 113 if(deep[u] > deep[v]) 114 ans = max(ans, cal(postion[v], postion[u], uk)); 115 else 116 ans = max(ans, cal(postion[u], postion[v], vk)); 117 return ans; 118 } 119 120 vector<int> block[LEN]; 121 vector< pair< pair<int, int>, int > > qs[LEN+5]; 122 vector< pair< pair<int, int>, pair<int, int> > > qy[N]; 123 void solve(int k){ 124 for(int i = 1; i <= n; i++){ 125 int u = trID[i]; 126 block[deep[u]%k].push_back(u); 127 } 128 label = 0; 129 for(int i = 0; i < k; i++){ 130 qL[i] = label + 1; 131 for(auto x: block[i]) 132 nS[++label] = postion[x]; 133 qR[i] = label; 134 } 135 build(1, 1, n); 136 for(auto &x: qs[k]) 137 answer[x.second] = question(x.first.first, x.first.second, k); 138 for(int i = 0; i < k; i++) 139 block[i].clear(); 140 qs[k].clear(); 141 } 142 143 int sk[N], tp;//sk为栈, tp为栈顶指针 144 145 void dfs(int u){ 146 sk[++tp] = u; 147 for(auto &x: qy[u]){ 148 for(int i = tp-x.first.second; 149 i > 0 && deep[sk[i]] >= deep[x.first.first]; 150 i -= x.second.first) 151 answer[x.second.second] = max(answer[x.second.second], arr[sk[i]]); 152 } 153 qy[u].clear(); 154 for(auto v : G[u]){ 155 if(v ^ fa[u]) 156 dfs(v); 157 } 158 --tp; 159 } 160 161 int main() 162 { 163 //freopen("dataB.txt", "r", stdin); 164 int T, kase = 0; 165 scanf("%d", &T); 166 while(T--){ 167 scanf("%d%d", &n, &m); 168 for(int i = 1; i <= n; i++) 169 scanf("%d", &arr[i]); 170 int u, v, k; 171 for(int i = 1; i <= n; i++) 172 G[i].clear(); 173 for(int i = 1; i <= n-1; i++){ 174 scanf("%d%d", &u, &v); 175 G[u].push_back(v); 176 G[v].push_back(u); 177 } 178 label = 0; 179 dfs1(1, 1); 180 dfs2(1, 1); 181 //debug(); 182 for(int i = 0; i < m; i++){ 183 scanf("%d%d%d", &u, &v, &k); 184 if(k >= LEN){ 185 int f = lca(u, v); 186 int d = (deep[u]+deep[v]-2*deep[f]+1)%k; 187 if(u ^ f) 188 qy[u].push_back({ {f, k-1}, {k, i} }); 189 if(v ^ f) 190 qy[v].push_back({ {f, d}, {k, i} }); 191 }else{ 192 qs[k].push_back({ {u, v}, i }); 193 } 194 } 195 memset(answer, 0, sizeof(answer)); 196 for(int i = 1; i < LEN; i++) 197 if(qs[i].size()) 198 solve(i); 199 tp = 0; 200 dfs(1); 201 printf("Case #%d:\n", ++kase); 202 for(int i = 0; i < m; i++) 203 printf("%d\n", answer[i]); 204 } 205 206 return 0; 207 }