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的稳定性 思路: 首先删边考 ...
随机推荐
- 漏洞复现-vsftpd-v2.3.4
vsftpd-2.3.4早期版本存在恶意的后门,在钟馗之眼上目前骇客以收到如此的主机,不过很多的服务器都已经被修复过,但总有漏网之鱼,有兴趣的小伙伴不妨去试试 0×01前言: vsftpd-2.3.4 ...
- Spring boot中使用log4j
我们知道,Spring Boot中默认日志工具为logback,但是对于习惯了log4j的开发者,Spring Boot依然可以很好的支持,只是需要做一些小小的配置功能.Spring Boot使用lo ...
- Android v7包下Toolbar和ActionBarActivity实现后退导航效果
android.support.v7包下的ToolBar和ActionBarActivity,均自带后退导航按钮,只是要手动开启,让它显示出来.先来看看ToolBar,页面前台代码: <andr ...
- 【5】JMicro微服务-熔断降级
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 1. 使用服务熔断降级特性,必须先启动Pubsub服务,服务监听服务,熔断器服务3个服务 先启动Pubsub及服务监听两 ...
- docker学习实践之路[第四站]利用pm2镜像部署node应用
拉取keymetrics/pm2-docker-alpine:8镜像 docker pull keymetrics/pm2-docker-alpine: [8]为node镜像的版本号: 建立Docke ...
- 线程中的同步辅助类Exchanger
Exchanger 允许两个线程在 collection 点交换对象,它在多流水线设计中是有用的. 允许两条线程之间交换数据.Exchanger的exchange方法是阻塞的,当其他线程也调用了该方法 ...
- js便签笔记(12)——浏览TOM大叔博客的学习笔记 part2
1. 前言 昨天写了<js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1>,简单记录了几个问题.part1的重点还是在于最后那个循环创建函数的问题,也就是多个子函数公用一个闭 ...
- ElasticSearch 基础<转载>
使用curl命令操作elasticsearch 大岩不灿 发表于 2015年4月25日 浏览 13,463 次 第一:_cat系列_cat系列提供了一系列查询elasticsearch集群状态的接口. ...
- Ubuntu中安装Sublime Text 3并安装Package Control
最近在学习Linux的使用,并在Linux中进行python开发练习.在学习过程中,了解到Sublime Text3是一款备受开发者推崇的代码编辑器,因此在Ubuntu中安装了Sublime Text ...
- React Native从入门到放弃之环境搭建
官网 https://facebook.github.io/react-native/ 中文网站 http://reactnative.cn/ 相关文档 http://www.lcode.org/史上 ...