一棵带边权的树,多次询问 $x$ 到编号为 $[l,r]$ 的点最短距离是多少

$n \leq 100000$

sol:

动态点分治,每层重心维护到所有点的距离

查询的时候在管辖这个点的 log 层线段树里查就可以了

因为这样每一层的答案只会漏而不会错,所以正确性有保障

不会写点分治了...orz

#include <bits/stdc++.h>
#define LL long long
#define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
#define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
using namespace std;
inline int read() {
int x = , f = ;
char ch;
for (ch = getchar(); !isdigit(ch); ch = getchar())
if (ch == '-')
f = -f;
for (; isdigit(ch); ch = getchar()) x = * x + ch - '';
return x * f;
}
const int maxn = , inf = 1e9;
int n, m;
int first[maxn], to[maxn << ], nx[maxn << ], val[maxn], cnt;
inline void add(int u, int v, int w) {
to[++cnt] = v;
val[cnt] = w;
nx[cnt] = first[u];
first[u] = cnt;
}
int sig, root, size[maxn], pa[maxn], f[maxn], vis[maxn];
inline void findroot(int x, int fa) {
size[x] = ;
f[x] = ;
for (int i = first[x]; i; i = nx[i]) {
if ((to[i] == fa) || (vis[to[i]]))
continue;
findroot(to[i], x);
size[x] += size[to[i]];
f[x] = max(f[x], size[to[i]]);
}
f[x] = max(f[x], sig - size[x]);
if (f[x] < f[root])
root = x;
}
inline void build(int x) {
vis[x] = ;
for (int i = first[x]; i; i = nx[i]) {
if (vis[to[i]])
continue;
root = ;
sig = size[to[i]];
findroot(to[i], x);
pa[root] = x;
build(root);
}
}
namespace sp_lca {
int size[maxn], dep[maxn], fa[maxn], bl[maxn], dp[maxn];
inline void dfs1(int x) {
size[x] = ;
for (int i = first[x]; i; i = nx[i]) {
if (to[i] == fa[x])
continue;
fa[to[i]] = x;
dep[to[i]] = dep[x] + ;
dp[to[i]] = dp[x] + val[i];
dfs1(to[i]);
size[x] += size[to[i]];
}
}
inline void dfs2(int x, int col) {
int k = ;
bl[x] = col;
for (int i = first[x]; i; i = nx[i])
if (to[i] != fa[x] && size[to[i]] > size[k])
k = to[i];
if (!k)
return;
dfs2(k, col);
for (int i = first[x]; i; i = nx[i])
if (to[i] != fa[x] && to[i] != k)
dfs2(to[i], to[i]);
}
inline void init() {
dfs1();
dfs2(, );
}
inline int lca(int x, int y) {
while (bl[x] != bl[y]) {
if (dep[bl[x]] < dep[bl[y]])
swap(x, y);
x = fa[bl[x]];
}
return dep[x] < dep[y] ? x : y;
}
} // namespace sp_lca
inline int dis(int x, int y) { return sp_lca::dp[x] + sp_lca::dp[y] - (sp_lca::dp[sp_lca::lca(x, y)] << ); }
int rt[maxn], ls[maxn << ], rs[maxn << ], va[maxn << ], ToT;
inline void Insert(int &x, int l, int r, int pos, int v) {
if (!x)
x = ++ToT, va[x] = inf;
va[x] = min(va[x], v);
if (l == r)
return;
int mid = (l + r) >> ;
if (pos <= mid)
Insert(ls[x], l, mid, pos, v);
else
Insert(rs[x], mid + , r, pos, v);
}
inline int query(int x, int l, int r, int L, int R) {
if (!x)
return inf;
if (L <= l && r <= R)
return va[x];
int mid = (l + r) >> , res = inf;
if (L <= mid)
res = min(res, query(ls[x], l, mid, L, R));
if (R > mid)
res = min(res, query(rs[x], mid + , r, L, R));
return res;
}
int main() {
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n = read();
rep(i, , n) {
int u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
}
f[] = inf;
root = ;
sig = n;
findroot(, );
build(root);
sp_lca ::init();
rep(i, , n) for (int x = i; x; x = pa[x]) Insert(rt[x], , n, i, dis(x, i));
// rep(i, 1, n) cout << pa[i] << endl;
int q = read();
while (q--) {
int u = read(), v = read(), x = read();
int cur = x, ans = inf;
while (cur) {
ans = min(ans, query(rt[cur], , n, u, v) + dis(cur, x));
cur = pa[cur];
}
cout << ans << endl;
}
}

「2017 山东三轮集训 Day7」Easy的更多相关文章

  1. 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树

    题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...

  2. #6145. 「2017 山东三轮集训 Day7」Easy 动态点分治

    \(\color{#0066ff}{题目描述}\) JOHNKRAM 最近在参加 C_SUNSHINE 举办的聚会. C 国一共有 n 座城市,这些城市由 n−1 条无向道路连接.任意两座城市之间有且 ...

  3. LOJ #6145. 「2017 山东三轮集训 Day7」Easy 点分树+线段树

    这个就比较简单了~ Code: #include <cstdio> #include <algorithm> #define N 100004 #define inf 1000 ...

  4. 「2017 山东三轮集训 Day7 解题报告

    「2017 山东三轮集训 Day7」Easy 练习一下动态点分 每个点开一个线段树维护子树到它的距离 然后随便查询一下就可以了 注意线段树开大点... Code: #include <cstdi ...

  5. 「2017 山东三轮集训 Day1」Flair

    模拟赛的题 好神仙啊 题面在这里 之前的Solution很蠢 现在已经update.... 题意 有$ n$个商品价格均为$ 1$,您有$ m$种面值的货币,面值为$ C_1..C_m$ 每种物品你有 ...

  6. 【loj6142】「2017 山东三轮集训 Day6」A 结论题+Lucas定理

    题解: 当奇数 发现答案就是C(n,1)^2+C(n,3)^2+...C(n,n)^2 倒序相加,发现就是C(2n,n) 所以答案就是C(2n,n)/2 当偶数 好像并不会证 打表出来可以得到 2.当 ...

  7. loj #6138. 「2017 山东三轮集训 Day4」Right

    题目: 题解: 暴力一波 \(SG\) 函数可以发现这么一个规律: \(p\) 为奇数的时候 : \(SG(n) = n \% 2\) \(p\) 为偶数的时候 : \(SG(n) = n \% (p ...

  8. loj #6136. 「2017 山东三轮集训 Day4」Left

    题目: 题解: 我们可以发现所有的交换器都是一个位置连接着下一层左侧的排序网络,另一个位置连着另一侧的排序网络. 而下一层是由两个更低阶的排序网络构成的. 两个网络互不干扰.所以我们可以通过第一行和最 ...

  9. Loj #6142. 「2017 山东三轮集训 Day6」A

    link: https://loj.ac/problem/6142 推完一波式子之后发现求的是:ΣC(N,i)^2, 其中i是偶数. 然后就可以卢卡斯乱搞了,分奇偶和之前的答案合并就好了233. #i ...

随机推荐

  1. mysql分组查询

    有一张学生选课表 Table: Subject_Selection Subject Semester Attendee --------------------------------- ITB001 ...

  2. RHEL(或CentOS)中关于逻辑卷( Logical Volume Manager,LVM)的一些概念及使用LVM的例子

    1.逻辑卷(logical volumes,LV) 卷管理在物理存储之上的抽象层,它使你能够创建逻辑存储卷.和直接使用物理存储相比,这从很多方面提供了更大的灵活性.比如,使用逻辑卷,你将不再受物理磁盘 ...

  3. 【HackerRank】Insertion Sort Advanced Analysis(归并排序求数列逆序数对)

    Insertion Sort is a simple sorting technique which was covered in previous challenges. Sometimes, ar ...

  4. SOA 面向服务架构 阅读笔记(三)

    7 SOA的主要组件 7.1企业服务总线ESB ESB负责SOA组件之间的互相通信;SOA注册中心的资源库包含表示SOA组件的位置的重要的引用信息: 业务流程编排管理器提供人与人,人与流程,以及流程的 ...

  5. /var/spool/clientmqueue 爆满问题

    当你使用简单的sendmail发邮件的时候,或者系统默认要发一些邮件(比如cron发的邮件)的时候,首先会把邮件拷贝到这个目录里,然后等待MTA(mail transfer agent) 来处理,MT ...

  6. 轻松掌握XMLHttpRequest对象------【这是.net 版本】

    轻松掌握XMLHttpRequest对象 XmlHttp是什么? 最通用的定义为:XmlHttp是一套可以在Javascript.VbScript.Jscript等脚本语言中通过http协议传送或从接 ...

  7. Node.js的原型继承函数 util.inherits

    转自:http://sentsin.com/web/179.html util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.Java ...

  8. JavaWeb -- Servlet+JSP+JavaBean(MVC)模式

    Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据. Servlet+JSP ...

  9. Spring初学之spring的事务管理xml

    所有的java类都是用的上一篇文章:Spring初学之spring的事务管理 不同的是,这时xml配置事务,所以就要把java类中的那些关于spring的注解都删掉,然后在xml中配置,Applica ...

  10. Java中常见的比较器的实现方法

    在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题. 通常对象之间的比较可以从两个方面去看: 第一个方面:对象的地址是否一样,也就是是否引用自同一个对象.这种方式可以直接使用& ...