This world need more Zhu

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5840

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.

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.

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.

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

题意

给你一棵树,然后Q次询问,每个询问给你u,v,k,问你从u到v,每次跳k步,然后路过的最大值是多少。

题解:

k大的时候,肯定XJB暴力就好了。

但是这个暴力也不能纯暴力呀,往上跳这个玩意儿得做到O1才行。

这个你就按照dfs序的顺序去维护就好了,然后下标减去k,就表示这个点往上跳了k步。

K小的时候,XJB暴力就不行了,这个就得机智一点。

我们考虑询问,其实可以把询问拆成两个,u到lca(u,v)中,deep%k=a的最大值,和v到lca(u,v)中,deep%k=b的最大值。

询问拆开之后,我们对于熟练剖分之后,把所有点%k等于相同值的点扔在一起,然后就相当于我们拆成了k棵树,每棵树的形态都是一样的。

然后我们随便拿一颗线段树莽一波就好了。

至于为什么我的块是20,大概是因为前面瞎JB暴力的常数比树链剖分的常数低吧?

【其实大概是傻逼出题人出的数据太TM水了吧?

代码

#include <bits/stdc++.h>
#define ls (o << 1)
#define rs (o << 1 | 1)
#define FI first
#define SE second
using namespace std; const int N = 100005; const int MAGIC = 20; int a[N]; vector <int> G[N]; int seq[N], tin[N], fa[N], dep[N], top[N], son[N], sz[N], label; void dfs1(int u, int father) {
fa[u] = father;
son[u] = 0; sz[u] = 1;
for(auto v : G[u]) {
if(v == father) continue;
dep[v] = dep[u] + 1;
dfs1(v, u);
sz[u] += sz[v];
if(sz[v] > sz[son[u]])
son[u] = v;
}
} void dfs2(int u, int anc) {
top[u] = anc; tin[u] = ++ label;
seq[label] = u;
if(son[u]) dfs2(son[u], anc);
for(auto v : G[u]) {
if(v == fa[u] || v == son[u])
continue;
dfs2(v, v);
}
} inline int lca(int u, int v) {
while(top[u] ^ top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
} vector < pair < pair <int, int>, int> > qs[MAGIC + 5]; int n, m, ans[N]; int nS[N], cL[N], cR[N]; struct Seg {
int l, r, v;
} T[N << 2]; void build(int o, int l, int r) {
T[o].l = l; T[o].r = r;
if(l == r) { T[o].v = a[seq[nS[l]]]; return; }
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
T[o].v = max(T[ls].v, T[rs].v);
} int query(int o, int l, int r) {
if(T[o].l == l && T[o].r == r) return T[o].v;
int mid = (T[o].l + T[o].r) >> 1;
if(r <= mid) return query(ls, l, r);
if(l > mid) return query(rs, l, r);
return max(query(ls, l, mid), query(rs, mid + 1, r));
} inline int cal(int l, int r, int k) {
if(cL[k] > cR[k]) return 0;
l = lower_bound(nS + cL[k], nS + cR[k] + 1, l) - nS;
r = upper_bound(nS + cL[k], nS + cR[k] + 1, r) - nS - 1;
return l <= r ? query(1, l, r) : 0;
} int ask(int u, int v, int k) {
int ret = -1, f = lca(u, v);
int uk = (dep[u] + 1) % k;
int vk = (dep[f] + (k - (dep[u] - dep[f] + 1) % k)) % k;
while(top[u] ^ top[v]) {
if(dep[top[u]] > dep[top[v]]) {
ret = max(ret, cal(tin[top[u]], tin[u], uk));
u = fa[top[u]];
} else {
ret = max(ret, cal(tin[top[v]], tin[v], vk));
v = fa[top[v]];
}
}
if(dep[u] > dep[v]) {
ret = max(ret, cal(tin[v], tin[u], uk));
} else {
ret = max(ret, cal(tin[u], tin[v], vk));
}
return ret;
} vector <int> E[MAGIC]; void small_case(int k) {
for(int i = 1; i <= n; ++ i) {
int u = seq[i];
E[dep[u] % k].push_back(u);
}
label = 0;
for(int i = 0; i < k; ++ i) {
cL[i] = label + 1;
for(auto x : E[i])
nS[++ label] = tin[x];
cR[i] = label;
}
build(1, 1, n);
for(auto &x : qs[k])
ans[x.SE] = ask(x.FI.FI, x.FI.SE, k);
for(int i = 0; i < k; ++ i)
E[i].clear();
qs[k].clear();
} vector < pair < pair <int, int>, pair <int, int> > > qy[N]; int sk[N], tp; void dfs(int u) {
sk[++ tp] = u;
for(auto &x : qy[u]) {
for(int i = tp - x.FI.SE; i > 0 && dep[sk[i]] >= dep[x.FI.FI]; i -= x.SE.FI)
ans[x.SE.SE] = max(ans[x.SE.SE], a[sk[i]]);
}
qy[u].clear();
for(auto v : G[u])
if(v ^ fa[u])
dfs(v);
-- tp;
} int main() {
int T, cas = 1;
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++ i) {
scanf("%d", a + i);
}
for(int u, v, i = 1; i < n; ++ i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(ans, 0, m * sizeof(int));
label = 0;
dfs1(1, 1); dfs2(1, 1);
for(int i = 0; i < m; ++ i) {
int u, v, k;
scanf("%d%d%d", &u, &v, &k);
if(k >= MAGIC) {
int f = lca(u, v), d = (dep[u] + dep[v] - 2 * dep[f] + 1) % k;
if(u ^ f) qy[u].push_back( { {f, k - 1}, {k, i} } );
if(v ^ f) qy[v].push_back( { {f, d}, {k, i} } );
} else {
qs[k].push_back( { {u, v}, i } );
}
}
for(int i = 1; i < MAGIC; ++ i)
if(qs[i].size())
small_case(i);
tp = 0; dfs(1);
printf("Case #%d:\n", cas ++);
for(int i = 0; i < m; ++ i)
printf("%d\n", ans[i]);
for(int i = 1; i <= n; ++ i)
G[i].clear();
}
return 0;
}

HDU 5840 This world need more Zhu 树链剖分+暴力的更多相关文章

  1. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  2. HDU 3966:Aragorn's Story(树链剖分)

    http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:有n个点n-1条边,每个点有一个权值,有两种操作:询问一个点上权值是多少和修改u到v这条链上的权值. ...

  3. HDU - 6393 Traffic Network in Numazu(树链剖分+基环树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6393 题意 给n个点和n条边的图,有两种操作,一种修改边权,另一种查询u到v的最短路. 分析 n个点和n条边,实 ...

  4. hdu 6393 Traffic Network in Numazu (树链剖分+线段树 基环树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6393 思路:n个点,n条边,也就是基环树..因为只有一个环,我们可以把这个环断开,建一个新的点n+1与之相 ...

  5. Hdu 5052 Yaoge’s maximum profit(树链剖分)

    题目大意: 给出一棵树.每一个点有商店.每一个商店都有一个价格,Yaoge每次从x走到y都能够在一个倒卖商品,从中得取利益.当然,买一顶要在卖之前.可是没次走过一条路,这条路上的全部商品都会添加一个v ...

  6. HDU 5614 Baby Ming and Matrix tree 树链剖分

    题意: 给出一棵树,每个顶点上有个\(2 \times 2\)的矩阵,矩阵有两种操作: 顺时针旋转90°,花费是2 将一种矩阵替换为另一种矩阵,花费是10 树上有一种操作,将一条路经上的所有矩阵都变为 ...

  7. HDU 5893 List wants to travel(树链剖分)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5893 [题目大意] 给出一棵树,每条边上都有一个边权,现在有两个操作,操作一要求将x到y路径上所有边 ...

  8. HDU 3966 Aragorn&#39;s Story(树链剖分)

    HDU Aragorn's Story 题目链接 树抛入门裸题,这题是区间改动单点查询,于是套树状数组就OK了 代码: #include <cstdio> #include <cst ...

  9. HDU 5893 List wants to travel(树链剖分+线段树)

    题目链接 HDU5893 $2016$年$ICPC$沈阳网络赛的$B$题.这道题其和 BZOJ2243 基本一样 那道题我也写了题解 点这里 两道题的区别就是$BZOJ$这题是点的权值,这道题是边权. ...

随机推荐

  1. Spring Cloud (十三) Zuul:静态路由、静态过滤器与动态路由的实现

    前言 本文起笔于2018-06-26周二,接了一个这周要完成的开发任务,需要先等其他人的接口,可能更新的会慢一些,还望大家见谅.这篇博客我们主要讲Spring Cloud Zuul.项目地址:我的gi ...

  2. Windows bat 学习(高级)

    有一种叫做 Command Processor Extensions 的东西,即命令处理器扩展.他会使命令更加高级,功能更多. 在 cmd 里可以使用 ECHO %CMDEXTVERSION% 查看当 ...

  3. Docker学习笔记一 概念、安装、镜像加速

    本文地址:https://www.cnblogs.com/veinyin/p/10406378.html  Docker 是一个容器,可以想象成一个轻便的虚拟机,但不虚拟硬件和操作系统. 优点:启动快 ...

  4. Codeforces 238 div2 A. Gravity Flip

    题目链接:http://codeforces.com/contest/405/problem/A 解题报告:有n列箱子竖直放置,每列箱子上都有数量不等的箱子,这些箱子之间没有固定,当重力方向改为平行向 ...

  5. Strange Queries(莫队)

    题目 You are given an array with n integers a1, a2, ..., an, and q queries to answer. Each query consi ...

  6. 论参数self

    此篇文章仅适用于py3.在py2中,a.fuc(x)中的参数x必须是 类a的实例对象,而py3则可以是任意对象.参考绑定方法和非绑定方法 当一个对象添加了一个方法,并且此方法的第一个参数为self,或 ...

  7. C. NN and the Optical Illusion(几何)

    题目链接:http://codeforces.com/contest/1100/problem/C 题目大意:给你n和r,n指的是有n个圆围在里面的圆的外面,r指的是里面的圆的半径,然后让你求外面的圆 ...

  8. Linux内核入门(六)—— __attribute__ 机制【转】

    转自:https://blog.csdn.net/yunsongice/article/details/5538020 GNU C的一大特色(却不被初学者所知)就是__attribute__机制.__ ...

  9. mysql及linux发行版下载源

    MySQL国内镜像资源 搜狐开源镜像站:http://mirrors.sohu.com/ 国内开源镜像站点汇总 http://segmentfault.com/a/1190000000375848   ...

  10. [Android]使用 Eclipse 给 APK 签名时遇到的两个问题及解决办法

    问题 今天用 APK 反编译工具看了一下自己项目生成的 APK 文件,发现代码并没有混淆,于是设置了用 ProGuard 混淆代码,可是混淆是必须在非 Debug 模式才会生效的,即使你是以 Rele ...