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. Linux遇到的问题(一)Ubuntu报“xxx is not in the sudoers file.This incident will be reported” 错误解决方法

    提示错误信息 www@iZ236j3sofdZ:~$ ifconfig Command 'ifconfig' is available in '/sbin/ifconfig' The command ...

  2. [转载]Supporting OData $inlinecount with the new Web API OData preview package

    http://www.strathweb.com/2012/08/supporting-odata-inlinecount-with-the-new-web-api-odata-preview-pac ...

  3. 20155227 2016-2017-2 《Java程序设计》第八周学习总结

    20155227 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 NIO与NIO2 NIO即New IO.java从JDK1.4开始提供了NIO,在JAVA ...

  4. 重启虚拟目录或站点,不重启iis

    更改站点或虚拟目录的.net Framework 版本会导致重启整个iis服务,所以需要单独重启某个站点或虚拟目录 首先右键点击网站-所有任务-将配置保存到一个文件,从文件中查找到 Location ...

  5. slf4j MDC使用

    slf4j MDC使用 最近也是在项目代码里发现一个地方有个MDC.put(),忍不住好奇点了进去,于是知道了MDC这个东西,细研究一下,发现还真是个好东西. MDC解决了什么问题 MDC全名Mapp ...

  6. 从requests源码分析中学习python(一)

    v2ex同步更新:https://www.v2ex.com/t/500081 微信公众号:python学习开发 分析源码,看大神的代码是一种学习的好方法,让我从中学到很多以前不知道的知识,这次打算从大 ...

  7. 004_on-my-zsh漂亮的shell

    一. http://www.cnblogs.com/GarveyCalvin/p/4301235.html 二. 前言:Zsh可配置性强,用户可以自定义配置,个性化强.Zsh tab补全更强大,该功能 ...

  8. make distclean

    清空bin目录make dirclean 清空所有相关的东西,包括下载的软件包,配置文件,feeds内容等make distclean 这个命令会删除feeds目录及其下面的所有的文件,直接结果就是运 ...

  9. 网易与Google合作发布开源UI自动化测试方案 牛逼:Google 方面评价,这可能是目前世界上最好的 Android 游戏自动化测试方案。

    美西时间 3 月 19 日,在 GDC 开幕第一天的 Google 开发者专场,Google 发布了一款由网易研发的 UI 自动化测试方案:Airtest Project.Google 方面评价,这可 ...

  10. Jmeter之逻辑控制器(Logic Controller)【转】

    Jmeter之逻辑控制器(Logic Controller) 前言: 1. Jmeter官网对逻辑控制器的解释是:“Logic Controllers determine the order in w ...