题意

题目链接

Sol

首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献。

再把每个点与\(k\)的lca的距离差分一下,则只需要统计每个点与\(k\)的lca深度。这个东西等价于所有的链与\(k\)到根的链的并。

树剖+主席树维护一下。这题的主席树需要区间加1,可以标记永久化合并标记

复杂度\(O(n\log ^2n)\)

#include<bits/stdc++.h>
#define Pair pair<LL, LL>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
//#define int long long
#define LL long long
#define ull unsigned long long
#define Fin(x) {freopen(#x".in","r",stdin);}
#define Fout(x) {freopen(#x".out","w",stdout);}
using namespace std;
const int MAXN = 2e5 + 10, mod = 1e9 + 7, INF = 1e9 + 10;
const double eps = 1e-9;
template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;}
template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);}
template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;}
template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;}
template <typename A> inline void debug(A a){cout << a << '\n';}
template <typename A> inline LL sqr(A x){return 1ll * x * x;}
template <typename A, typename B> inline LL fp(A a, B p, int md = mod) {int b = 1;while(p) {if(p & 1) b = mul(b, a);a = mul(a, a); p >>= 1;}return b;}
template <typename A> A inv(A x) {return fp(x, mod - 2);}
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
LL lastans;
int type, N, Q, p[MAXN], fa[MAXN], top[MAXN], dep[MAXN], son[MAXN], siz[MAXN], dfn[MAXN], rev[MAXN], times;
LL Esum[MAXN], sdis[MAXN], valE[MAXN];
vector<Pair> v[MAXN];
void dfs(int x, int _fa) {
fa[x] = _fa; dep[x] = dep[_fa] + 1; siz[x] = 1;
for(auto &tmp : v[x]) {
int to = tmp.first, w = tmp.se;
if(to == _fa) continue;
Esum[to] = Esum[x] + w; valE[to] = w;
dfs(to, x);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;
}
}
void dfs2(int x, int topf) {
top[x] = topf; dfn[x] = ++times; rev[times] = x;
if(!son[x]) return ;
dfs2(son[x], topf);
for(auto &to : v[x]) {
if(top[to.fi]) continue;
dfs2(to.fi, to.fi);
}
}
int LCA(int x, int y) {
while(top[x] ^ top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
int rt[MAXN], ls[MAXN * 80], rs[MAXN * 80], cnt;
LL sumc[MAXN * 80], sum[MAXN * 80], lzy[MAXN * 80];
void Build(int &k, int l, int r) {
k = ++cnt;
if(l == r) {sumc[k] = valE[rev[l]]; return ;}
int mid = l + r >> 1;
Build(ls[k], l, mid); Build(rs[k], mid + 1, r);
sumc[k] = sumc[ls[k]] + sumc[rs[k]];
}
Pair operator + (const Pair a, const Pair b) {
return {a.fi + b.fi, a.se + b.se};
}
void Add(int &k, int l, int r, int ql, int qr) {
++cnt; int nw = cnt;
ls[nw] = ls[k]; rs[nw] = rs[k]; sumc[nw] = sumc[k];
sum[nw] = sum[k]; lzy[nw] = lzy[k];
k = cnt;
if(ql <= l && r <= qr) {
lzy[k]++, sum[k] += sumc[k];
return ;
}
int mid = l + r >> 1;
if(ql <= mid) Add(ls[k], l, mid, ql, qr);
if(qr > mid) Add(rs[k], mid + 1, r, ql, qr);
sum[k] = sum[ls[k]] + sum[rs[k]] + lzy[k] * sumc[k];
}
Pair Query(int k, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return {sum[k], sumc[k]};
Pair res = {0, 0};
int mid = l + r >> 1;
if(ql <= mid) res = res + Query(ls[k], l, mid, ql, qr);
if(qr > mid) res = res + Query(rs[k], mid + 1, r, ql, qr);
res.fi += 1ll * res.se * lzy[k];
return res;
}
void insert(int x) {
int pre = x;
rt[x] = rt[fa[x]];
x = p[x];
while(x)Add(rt[pre], 1, N, dfn[top[x]], dfn[x]), x = fa[top[x]];
}
void dfs3(int x, int fa) {
sdis[x] = sdis[fa] + Esum[p[x]];
insert(x);
for(auto &to : v[x])
if(to.fi != fa) dfs3(to.fi, x);
} LL solve(int u, int k) {
if(!k) return 0;
LL res = sdis[k] + 1ll * dep[k] * Esum[u];
while(u) {
res -= Query(rt[k], 1, N, dfn[top[u]], dfn[u]).fi << 1;
u = fa[top[u]];
}
return res;
}
signed main() {
type = read(); N = read(); Q = read();
for(int i = 1; i <= N - 1; i++) {
int x = read(),y = read(), w = read();
v[x].push_back({y, w});
v[y].push_back({x, w});
}
for(int i = 1; i <= N; i++) p[i] = read();
dfs(1, 0);
dfs2(1, 1);
Build(rt[0], 1, N);
dfs3(1, 0);
while(Q--) {
int tu = read() ^ (lastans * type), tv = read() ^ (lastans * type), tk = read() ^ (lastans * type);
lastans = solve(tk, tu) + solve(tk, tv) - solve(tk, LCA(tu, tv)) - solve(tk, fa[LCA(tu, tv)]);
cout << lastans << '\n';
}
return 0;
}

loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)的更多相关文章

  1. Loj #6073.「2017 山东一轮集训 Day5」距离

    Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...

  2. loj#6073. 「2017 山东一轮集训 Day5」距离(费用流)

    题意 题目链接 Sol 我们可以把图行列拆开,同时对于行/列拆成很多个联通块,然后考虑每个点所在的行联通块/列联通块的贡献. 可以这样建边 从S向每个行联通块连联通块大小条边,每条边的容量为1,费用为 ...

  3. 「2017 山东一轮集训 Day5」距离

    /* 写完开店再写这个题目顿时神清气爽, 腰也不疼了, 眼也不花了 首先考虑将询问拆开, 就是查询一些到根的链和点k的关系 根据我们开店的结论, 一个点集到一个定点的距离和可以分三部分算 那么就很简单 ...

  4. Loj #6069. 「2017 山东一轮集训 Day4」塔

    Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...

  5. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  6. 「2017 山东一轮集训 Day5」苹果树

    「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...

  7. LOJ #6074. 「2017 山东一轮集训 Day6」子序列

    #6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...

  8. loj #6077. 「2017 山东一轮集训 Day7」逆序对

    #6077. 「2017 山东一轮集训 Day7」逆序对   题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...

  9. LOJ #6119. 「2017 山东二轮集训 Day7」国王

    Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...

随机推荐

  1. python接口自动化(十九)--Json 数据处理---实战(详解)

    简介 上一篇说了关于json数据处理,是为了断言方便,这篇就带各位小伙伴实战一下.首先捋一下思路,然后根据思路一步一步的去实现和实战,不要一开始就盲目的动手和无头苍蝇一样到处乱撞,撞得头破血流后而放弃 ...

  2. javascript引擎执行的过程的理解--语法分析和预编译阶段

    一.概述 js是一种非常灵活的语言,理解js引擎的执行过程对于我们学习js是非常有必要的.看了很多这方便文章,大多数是讲的是事件循环(event loop)或者变量提升的等,并没有全面分析其中的过程. ...

  3. [译] PEP 255--简单的生成器

    我正打算写写 Python 的生成器,然而查资料时发现,引入生成器的 PEP 没人翻译过,因此就花了点时间翻译出来.如果在阅读时,你有读不懂的地方,不用怀疑,极有可能是我译得不到位.若出现这种情况,我 ...

  4. C# 操作Word页眉页脚——奇偶页/首页不同、不连续设置页码、复制页眉页脚、锁定页眉页脚、删除页眉页脚

    前言 本文是对Word页眉页脚的操作方法的进一步的阐述.在“C# 添加Word页眉页脚.页码”一文中,介绍了添加简单页眉页脚的方法,该文中的方法可满足于大多数的页眉页脚添加要求,但是对于比较复杂一点的 ...

  5. Java中三目运算符不为人知的坑

    一.思考题 以下代码可能有什么错误?为什么? import java.util.HashMap; import java.util.Map; public class Test { public st ...

  6. 配置rsync+inotify实时同步

    与上一篇同步做 配置rsync+inotify实时同步 1:调整inotify内核参数 在linux内核中,默认的inotify机制提供三个调控参数:max_queue_events.max_user ...

  7. cmd 执行Dcpromo错误:在该 SKU 上不支持 Active Directory 域服务安装向导,Windows Server 2008 R2 Enterprise 配置AD(Active Directory)域控制器

    今天,要安装AD域控制器,运行dcpromo结果提示:在该 SKU 上不支持 Active Directory 域服务安装向导. 以前弄的时候直接就通过了,这次咋回事?终于搞了大半天搞定了. 主要原因 ...

  8. Git报错 bad numeric config value '100000' for 'pack.windowmemory': out of range

    Git报错 bad numeric config value '10240M' for 'pack.windowmemory': out of range $ git config --edit -- ...

  9. JVM之GC算法、垃圾收集算法——标记-清除算法、复制算法、标记-整理算法、分代收集算法

    标记-清除算法 此垃圾收集算法分为“标记”和“清除”两个阶段: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记对象,它的标记过程前面已经说过——如何判断对象是否存活/死去 死去的对象就会 ...

  10. js随机背景颜色

    // 要求: 随机生成颜色RGB 核心点 :(0,0,0) rgb 每一组的数字取值范围是 0~255 // 需要随机生成 0~255 之间的整数 function getRandom(min, ma ...