#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <functional>
#include <bitset>
using namespace std;
#define eps 1e-10
#define N 200020
#define M 200020
#define mod 772002
#define G 3
#define inf 0x3f3f3f3f
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define ui unsigned int
char buf[32000000],*pt = buf,*o = buf;
int getint(){
int f = 1,x = 0;
while((*pt != '-') && (*pt < '0' || *pt > '9')) pt ++;
if(*pt == '-') f = -1,pt ++; else x = *pt++ - 48;
while(*pt >= '0' && *pt <= '9') x = x * 10 + *pt ++ - 48;
return x * f;
}
char getch(){
char ch;
while(*pt < 'A' || *pt > 'Z') pt ++;
ch=*pt;pt++;
return ch;
}
int n, q, fst[N], nxt[M], vv[M], e;
int a[N];
int B;
void init() {
memset(fst, -1, sizeof fst);
e = 0;
}
void add(int u, int v) {
vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}
int fa[N], dep[N], sz[N], son[N];
int tp[N];
int st[N], ed[N], lab[N], dc;
int ans[N];
int pos[N], num[N];
int mx[N << 2];
int L[N], R[N];
struct node {
int u, p, b, k, id;
node() {}
node(int u, int p, int b, int k, int id):
u(u), p(p), b(b), k(k), id(id) {}
bool operator < (const node &vt) const {
if(k != vt.k) return k < vt.k;
return b < vt.b;
}
}p[2 * N];
int tot;
void dfs1(int u, int p, int d) {
dep[u] = d;
fa[u] = p;
sz[u] = 1;
son[u] = 0;
int mx = 0;
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i];
if(v == p) continue;
dfs1(v, u, d + 1);
sz[u] += sz[v];
if(sz[v] > mx) son[u] = v, mx = sz[v];
}
}
void dfs2(int u, int anc) {
tp[u] = anc;
st[u] = ++dc;
lab[dc] = u;
if(son[u]) dfs2(son[u], anc);
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i];
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
ed[u] = dc;
}
int lca(int u, int v) {
while(tp[u] != tp[v]) {
if(dep[tp[u]] > dep[tp[v]]) swap(u, v);
v = fa[tp[v]];
}
if(dep[u] > dep[v]) swap(u, v);
return u;
}
int kfa(int u, int k) {
while(1) {
if(dep[u] - dep[tp[u]] < k) {
if(tp[u] == 1) return 0;
k -= dep[u] - dep[tp[u]] + 1;
u = fa[tp[u]];
}
else {
return lab[st[u]-k];
}
}
}
int bf_query(int u, int p, int k, int b) {
int t = ((dep[u] - b) % k + k) % k;
u = kfa(u, t);
int ret = 0;
while(u && dep[u] >= dep[p]) {
ret = max(ret, a[u]);
u = kfa(u, k);
}
return ret;
}
void build(int ll, int rr, int i) {
if(ll == rr) {
mx[i] = a[lab[pos[ll]]];
return;
}
build(lson);
build(rson);
mx[i] = max(mx[ls], mx[rs]);
}
int query(int l, int r, int ll, int rr, int i) {
if(ll == l && rr == r) return mx[i];
if(r <= md) return query(l, r, lson);
if(l > md) return query(l, r, rson);
return max(query(l, md, lson), query(md + 1, r, rson));
}
int calc_query(node x) {
int b = x.b;
if(L[b] == -1) return 0;
int u = x.u;
int p = x.p;
int ret = 0;
while(tp[u] != tp[p]) {
int l = st[tp[u]], r = st[u];
l = lower_bound(pos + L[b], pos + R[b] + 1, l) - pos;
r = upper_bound(pos + L[b], pos + R[b] + 1, r) - pos - 1;
if(l <= r) ret = max(ret, query(l, r, 1, n, 1));
u = fa[tp[u]];
}
int l = st[p], r = st[u];
l = lower_bound(pos + L[b], pos + R[b] + 1, l) - pos;
r = upper_bound(pos + L[b], pos + R[b] + 1, r) - pos - 1;
if(l <= r) ret = max(ret, query(l, r, 1, n, 1));
return ret;
}
int main() {
int cas, kk = 0;
scanf("%d", &cas);
while(cas--) {
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
B = sqrt(n + 0.5);
init();
for(int i = 1; i < n; ++i) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
dc = 0;
dfs1(1, 0, 0);
dfs2(1, 1);
tot = 0;
for(int i = 1; i <= q; ++i) {
ans[i] = 0;
int u, v, k;
scanf("%d%d%d", &u, &v, &k);
int fa = lca(u, v);
int a = (dep[u] + 1) % k;
int b = ((2 * dep[fa] - dep[u] - 1) % k + k) % k;
if(k > B) {
ans[i] = max(ans[i], bf_query(u, fa, k, a));
ans[i] = max(ans[i], bf_query(v, fa, k, b));
}
else {
p[++tot] = node(u, fa, a, k, i);
p[++tot] = node(v, fa, b, k, i);
}
}
sort(p + 1, p + tot + 1);
for(int i = 1, j; i <= tot; i = j + 1) {
j = i;
while(j + 1 <= tot && p[i].k == p[j+1].k) ++j;
int k = p[i].k;
for(int u = 0; u < k; ++u) num[u] = 0, L[u] = R[u] = -1;
for(int u = 1; u <= n; ++u) num[dep[lab[u]]%k]++;
for(int u = 1; u < k; ++u) num[u] += num[u-1];
for(int u = n; u >= 1; --u) pos[num[dep[lab[u]]%k]--] = u;
for(int u = 1, v; u <= n; u = v + 1) {
v = u;
while(v + 1 <= n && dep[lab[pos[u]]] % k == dep[lab[pos[v+1]]] % k) ++v;
L[dep[lab[pos[u]]]%k] = u;
R[dep[lab[pos[u]]]%k] = v;
}
build(1, n, 1);
for(int u = i; u <= j; ++u) {
ans[p[u].id] = max(ans[p[u].id], calc_query(p[u]));
}
}
printf("Case #%d:\n", ++kk);
for(int i = 1; i <= q; ++i) {
printf("%d\n", ans[i]);
}
}
return 0;
}
hdu 5840 This world need more Zhu (sqrt+树剖)
最新推荐文章于 2019-09-06 14:25:00 发布