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. HDU 4315 阶梯博弈变形

    n个棋子,其中第k个是红色的,每个棋子只能往上爬,而且不能越过.重叠其他棋子,谁将红色棋子移到顶部谁赢. 由于只能往上爬,所以很像阶梯博弈.这题有2个限制,棋子不能重叠,有红棋存在 首先不考虑红色棋, ...

  2. 何凯文每日一句打开||DAY8

  3. BAT及各大互联网公司2014前端笔试面试题--Html,Css篇(昨天有个群友表示写的简单了点,然后我无情的把他的抄了一遍)

    某个群友 http://www.cnblogs.com/coco1s/   很多面试题是我自己面试BAT亲身经历碰到的.整理分享出来希望更多的前端er共同进步吧,不仅适用于求职者,对于巩固复习前端基础 ...

  4. Spring Boot实战系列-----------邮件发送

    快速导航 添加Maven依赖 配置文件增加邮箱相关配置 Service.Test项目代码构建 五种邮件发送类型讲解 文本邮件 html邮件 附件邮件 html内嵌图片邮件 模板邮件 问题汇总 添加ma ...

  5. tf.Session()和tf.InteractiveSession()的区别

    官方tutorial是这么说的: The only difference with a regular Session is that an InteractiveSession installs i ...

  6. React-Native 之 ListView使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  7. 查询orcale运行的SQL语句记录

    select c.* from V$SQL c where c.MODULE='ukhis.exe' order by last_active_time desc

  8. ftp配置文件

    vsftpd配置文件采用“#”作为注释符,以“#”开头的行和空白行在解析时将被忽略,其余的行被视为配置命令行,每个配置命令的“=”两边不要留有空格.对于每个配置命令,在配置文件中还列出了相关的配置说明 ...

  9. Java中关于HashMap源码的研究

    1.基础知识 1.数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难. 2.链表 链表存储区间离散,占用内存比 ...

  10. 定制自己的new和delete:operator new 和 operator delete

    new和delete不同用法 基本用法 int * aptr = new int(10); delete aptr, aptr = nullptr; 上面的代码是我们最基本也是最常见的使用new和de ...