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
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 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
Then, you need to output the answer for every Liao's questions.
Sample Input
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
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
Source
//2017-08-08
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#define lson (id<<1)
#define rson ((id<<1)|1) using namespace std; const int N = ;
const int LEN = ;//块的大小
vector<int> G[N];
int n, m, label, answer[N]; //树链剖分
int arr[N];//arr[i]表示节点i的权值
int fa[N];//fa[i]表示节点i的父亲
int son[N];//son[i]表示节点i的重儿子
int top[N];//top[i]表示节点i所在重链的顶端节点
int size[N];//size[i]表示以节点i为根的子树的节点数
int deep[N];//deep[i]表示节点i的深度
int postion[N];//postion[i]表示节点i在线段树中的位置
int trID[N];//trID[i]表示节点i在剖分后的新编号 void dfs1(int u, int father){
fa[u] = father;
son[u] = ;
size[u] = ;
for(auto v: G[u]){
if(v == father)continue;
deep[v] = deep[u]+;
dfs1(v, u);
size[u] += size[v];
if(size[v] > size[son[u]])
son[u] = v;
}
} void dfs2(int u, int ancestor){
top[u] = ancestor;
postion[u] = ++label;
trID[label] = u;
if(son[u])
dfs2(son[u], ancestor);
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(deep[top[u]] < deep[top[v]])
swap(u, v);
u = fa[top[u]];
}
return deep[u] < deep[v] ? u : v;
} //线段树
struct Node{
int l, r, v;
}tree[N<<];
int nS[N], qL[N], qR[N]; void build(int id, int l , int r){
tree[id].l = l;
tree[id].r = r;
if(l == r){
tree[id].v = arr[trID[nS[l]]];
return;
}
int mid = (l+r)>>;
build(lson, l, mid);
build(rson, mid+, r);
tree[id].v = max(tree[lson].v, tree[rson].v);
} int query(int id, int l, int r){
if(tree[id].l == l && tree[id].r == r)
return tree[id].v;
int mid = (tree[id].l+tree[id].r)>>;
if(l > mid)return query(rson, l, r);
if(r <= mid)return query(lson, l, r);
return max(query(lson, l, mid), query(rson, mid+, r));
} inline int cal(int l, int r, int k){
if(qL[k] > qR[k])return ;
l = lower_bound(nS+qL[k], nS+qR[k]+, l)-nS;
r = upper_bound(nS+qL[k], nS+qR[k]+, r)-nS-;
if(l <= r)return query(, l, r);
else return ;
} int question(int u, int v, int k){
int ans = -, f = lca(u, v);
int uk = (deep[u] + )%k;
int vk = (deep[f] + (k - (deep[u]-deep[f]+)%k)) % k;
while(top[u] ^ top[v]){
if(deep[top[u]] > deep[top[v]]){
ans = max(ans, cal(postion[top[u]], postion[u], uk));
u = fa[top[u]];
}else{
ans = max(ans, cal(postion[top[v]], postion[v], vk));
v = fa[top[v]];
}
}
if(deep[u] > deep[v])
ans = max(ans, cal(postion[v], postion[u], uk));
else
ans = max(ans, cal(postion[u], postion[v], vk));
return ans;
} vector<int> block[LEN];
vector< pair< pair<int, int>, int > > qs[LEN+];
vector< pair< pair<int, int>, pair<int, int> > > qy[N];
void solve(int k){
for(int i = ; i <= n; i++){
int u = trID[i];
block[deep[u]%k].push_back(u);
}
label = ;
for(int i = ; i < k; i++){
qL[i] = label + ;
for(auto x: block[i])
nS[++label] = postion[x];
qR[i] = label;
}
build(, , n);
for(auto &x: qs[k])
answer[x.second] = question(x.first.first, x.first.second, k);
for(int i = ; i < k; i++)
block[i].clear();
qs[k].clear();
} int sk[N], tp;//sk为栈, tp为栈顶指针 void dfs(int u){
sk[++tp] = u;
for(auto &x: qy[u]){
for(int i = tp-x.first.second;
i > && deep[sk[i]] >= deep[x.first.first];
i -= x.second.first)
answer[x.second.second] = max(answer[x.second.second], arr[sk[i]]);
}
qy[u].clear();
for(auto v : G[u]){
if(v ^ fa[u])
dfs(v);
}
--tp;
} int main()
{
//freopen("dataB.txt", "r", stdin);
int T, kase = ;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)
scanf("%d", &arr[i]);
int u, v, k;
for(int i = ; i <= n; i++)
G[i].clear();
for(int i = ; i <= n-; i++){
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
label = ;
dfs1(, );
dfs2(, );
//debug();
for(int i = ; i < m; i++){
scanf("%d%d%d", &u, &v, &k);
if(k >= LEN){
int f = lca(u, v);
int d = (deep[u]+deep[v]-*deep[f]+)%k;
if(u ^ f)
qy[u].push_back({ {f, k-}, {k, i} });
if(v ^ f)
qy[v].push_back({ {f, d}, {k, i} });
}else{
qs[k].push_back({ {u, v}, i });
}
}
memset(answer, , sizeof(answer));
for(int i = ; i < LEN; i++)
if(qs[i].size())
solve(i);
tp = ;
dfs();
printf("Case #%d:\n", ++kase);
for(int i = ; i < m; i++)
printf("%d\n", answer[i]);
} return ;
}
HDU5840(SummerTrainingDay08-B 树链剖分+分块)的更多相关文章
- UOJ#435. 【集训队作业2018】Simple Tree 树链剖分,分块
原文链接www.cnblogs.com/zhouzhendong/p/UOJ435.html 前言 分块题果然是我这种蒟蒻写不动的.由于种种原因,我写代码的时候打错了很多东西,最致命的是数组开小了.* ...
- HDU5840 (分块+树链剖分)
Problem This world need more Zhu 题目大意 给一颗n个点的有点权的树,有m个询问,对于每个询问u,v,k,首先将点u到点v的最短路径上的所有点按顺序编号,u的编号为1, ...
- 【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count
很早之前用树链剖分写过,但是代码太长太难写,省选现场就写错了. #include<cstdio> #include<algorithm> #include<cstring ...
- jzoj5987. 【WC2019模拟2019.1.4】仙人掌毒题 (树链剖分+概率期望+容斥)
题面 题解 又一道全场切的题目我连题目都没看懂--细节真多-- 先考虑怎么维护仙人掌.在线可以用LCT,或者像我代码里先离线,并按时间求出一棵最小生成树(或者一个森林),然后树链剖分.如果一条边不是生 ...
- 【树链剖分 差分】bzoj3626: [LNOI2014]LCA
把LCA深度转化的那一步还是挺妙的.之后就是差分加大力数据结构了. Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
随机推荐
- Java虚拟机7:垃圾收集(GC)-2(并行和并发的区别)
1.并发编程下 这两个名词都是并发编程中的概念,在并发编程的模型下的定义: 并发:是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)运行多个程序. 并行:是多个或同 ...
- Python 爬虫(二十五) Cookie的处理--cookielib库的使用
Python中cookielib库(python3中为http.cookiejar)为存储和管理cookie提供客户端支持. 该模块主要功能是提供可存储cookie的对象.使用此模块捕获cookie并 ...
- 实现域名访问网站—nginx反向代理
今天在跟项目的时候,是否被耍了三个多小时,最后在我准备号材料准备他人求助的时候,在收集材料的时候,居然访问通了, 别问我为什么,我也不知道 ,哈哈哈哈(苦逼脸...) 分享出来,大家共同学习: 这个是 ...
- FunDA(17)- 示范:异常处理与事后处理 - Exceptions handling and Finalizers
作为一个能安全运行的工具库,为了保证占用资源的安全性,对异常处理(exception handling)和事后处理(final clean-up)的支持是不可或缺的.FunDA的数据流FDAPipeL ...
- Javascript如何避免连续调用中取到不存在的属性而导致报TypeError错?
背景: 在最近的 NODEJS 项目中,涉及到数据库的查询,回调函数里返回了查询结果,我这样做处理然后返回给前端: return results.collect_coupon[0].count 但是这 ...
- POJ 2685
#include <iostream> #include <string> #define MAXN 26 using namespace std; int _map[MAXN ...
- 分享:基于Dracula+Zenburn 自定制的pycharm主题配色文件
显示效果: PS:彩色配色,一是可以提高平时写代码的乐趣,另一个是,对视力相对比较好. 配置方法: 1. 在你本地的操作系统里,找到pycharm安装的时候,默认在C盘创建的文件夹colors:C:\ ...
- (转)python高级FTP
原文地址:http://www.itnose.net/detail/6754889.html高级FTP服务器1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. ...
- 通过修改CR0寄存器绕过SSDT驱动保护
为了安全起见,Windows XP及其以后的系统将一些重要的内存页设置为只读属性,这样就算有权力访问该表也不能随意对其修改,例如SSDT.IDT等.但这种方法很容易被绕过,我们只要将这些部分修改为可写 ...
- 手把手教你整合最优雅SSM框架
我们看招聘信息的时候,经常会看到这一点,需要具备 SSM 框架的技能, SpringMVC 可以完全替代 Struts,配合注解的方式,编程非常快捷,而且通过 restful 风格定义 url,让地址 ...