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

给定一颗有nnn个节点带边权的树,以及一个排列ppp,path(u,v)path(u, v)path(u,v)为u,vu, vu,v路径上的点集,dist(u,v)dist(u, v)dist(u,v)为u,vu, vu,v之间的最短路的长度。

有mmm次询问,每次给定u,v,ku, v, ku,v,k,要求∑i∈path(u,v)dist(pi,k)\sum\limits_{i \in path(u, v)}dist(p_i, k)i∈path(u,v)∑​dist(pi​,k),要求在线求解。

我们选定111号节点为根节点,定义d(i)d(i)d(i)为点iii到根节点的距离,考虑初始的∑i∈paht(u,v)dist(pi,k)\sum\limits_{i \in paht(u, v)} dist(p_i, k)i∈paht(u,v)∑​dist(pi​,k),有如下:
∑i∈path(u,v)dist(pi,k)=∑i∈path(u,v)(d(pi)+d(k)−2×d(lca(pi,k)))\sum\limits_{i \in path(u, v)}dist(p_i, k) = \sum_{i \in path(u, v)}\left(d(p_i) + d(k) - 2 \times d(lca(p_i, k))\right)\\ i∈path(u,v)∑​dist(pi​,k)=i∈path(u,v)∑​(d(pi​)+d(k)−2×d(lca(pi​,k)))
对于d(k)d(k)d(k)的计算,由于d(k)d(k)d(k)是一个定值,则这一部分的答案即为u,vu, vu,v间点的个数$ \times d(k)$。

对于d(pi)d(p_i)d(pi​)的计算,我们考虑树上差分前缀和来求解,我们定义sum[n]=∑i∈paht(1,n)d(pi)sum[n] = \sum\limits_{i \in paht(1, n)}d(p_i)sum[n]=i∈paht(1,n)∑​d(pi​),

则∑i∈path(u,v)d(pi)=sum[u]+sum[v]−sum[lca(u,v)]−sum[fa(lca(u,v))]\sum\limits_{i \in path(u, v)} d(p_i) = sum[u] + sum[v] - sum[lca(u, v)] - sum[fa(lca(u, v))]i∈path(u,v)∑​d(pi​)=sum[u]+sum[v]−sum[lca(u,v)]−sum[fa(lca(u,v))]。

最后一步,考虑最难算的∑i∈path(u,v)d(lca(pi,k))\sum\limits_{i \in path(u, v)} d(lca(p_i, k))i∈path(u,v)∑​d(lca(pi​,k)),可以仿照P4211 [LNOI2014]LCA这题的计算方式,

由于强制在线,所以这题必须用主席树,我们定义点iii所代表的主席树为从1−>i1->i1−>i上,也就是根节点到iii上,

点pi−>1p_i->1pi​−>1所代表的信息,最后我们只需要四颗主席树即可解决问题u+v−lca(u,v)−fa(lca(u,v))u + v - lca(u, v) - fa(lca(u, v))u+v−lca(u,v)−fa(lca(u,v))。

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 2e5 + 10;int head[N], to[N << 1], nex[N << 1], value[N << 1], cnt = 1;int p[N], n, m, type;int fa[N], sz[N], son[N], top[N], rk[N], id[N], dep[N], w[N], tot;int root[N], ls[N * 100], rs[N * 100], num;ll dis[N], len[N], s[N], sum[N * 100], lazy[N * 100];void add(int x, int y, int w) {to[cnt] = y;nex[cnt] = head[x];value[cnt] = w;head[x] = cnt++;
}void dfs1(int rt, int f) {fa[rt] = f, dep[rt] = dep[f] + 1, sz[rt] = 1;for (int i = head[rt]; i; i = nex[i]) {if (to[i] == f) {continue;}dis[to[i]] = dis[rt] + value[i];dfs1(to[i], rt);w[to[i]] = value[i];sz[rt] += sz[to[i]];if (!son[rt] || sz[son[rt]] < sz[to[i]]) {son[rt] = to[i];}}
}void dfs2(int rt, int tp) {rk[++tot] = rt, id[rt] = tot, len[tot] = w[rt], top[rt] = tp;if (!son[rt]) {return ;}dfs2(son[rt], tp);for (int i = head[rt]; i; i = nex[i]) {if (to[i] == fa[rt] || to[i] == son[rt]) {continue;}dfs2(to[i], to[i]);}
}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;
}void update(int &rt, int pre, int l, int r, int L, int R) {rt = ++num;ls[rt] = ls[pre], rs[rt] = rs[pre], sum[rt] = sum[pre], lazy[rt] = lazy[pre];sum[rt] += len[min(r, R)] - len[max(l, L) - 1];if (l >= L && r <= R) {lazy[rt] += 1;return ;}int mid = l + r >> 1;if (L <= mid) {update(ls[rt], ls[pre], l, mid, L, R);}if (R > mid) {update(rs[rt], rs[pre], mid + 1, r, L, R);}
}ll query(int u, int v, int f, int ff, int l, int r, int L, int R) {if (l >= L && r <= R) {return sum[u] + sum[v] - sum[f] - sum[ff];}ll ans = (lazy[u] + lazy[v] - lazy[f] - lazy[ff]) * (len[min(r, R)] - len[max(l, L) - 1]);int mid = l + r >> 1;if (L <= mid) {ans += query(ls[u], ls[v], ls[f], ls[ff], l, mid, L, R);}if (R > mid) {ans += query(rs[u], rs[v], rs[f], rs[ff], mid + 1, r, L, R);}return ans;
}void dfs(int rt, int f) {s[rt] = s[f] + dis[p[rt]];int cur = p[rt];root[rt] = root[f];while (cur) {update(root[rt], root[rt], 1, n, id[top[cur]], id[cur]);cur = fa[top[cur]];}for (int i = head[rt]; i; i = nex[i]) {if (to[i] == f) {continue;}dfs(to[i], rt);}
}ll query(int u, int v, int f, int ff, int rt) {ll ans = 0;while (rt) {ans += query(root[u], root[v], root[f], root[ff], 1, n, id[top[rt]], id[rt]);rt = fa[top[rt]];}return ans;
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);scanf("%d %d %d", &type, &n, &m);for (int i = 1, u, v, w; i < n; i++) {scanf("%d %d %d", &u, &v, &w);add(u, v, w);add(v, u, w);}for (int i = 1; i <= n; i++) {scanf("%d", &p[i]);}dfs1(1, 0);dfs2(1, 1);for (int i = 1; i <= n; i++) {len[i] += len[i - 1];}dfs(1, 0);ll ans = 0;for (int i = 1, u, v, k; i <= m; i++) {scanf("%d %d %d", &u, &v, &k);u = u ^ (ans * type), v = v ^ (ans * type), k = k ^ (ans * type);int f = lca(u, v), ff = fa[f];ans = (dep[u] + dep[v] - dep[f] - dep[ff]) * dis[k];ans += s[u] + s[v] - s[f] - s[ff];ans -= 2 * query(u, v, f, ff, k);printf("%lld\n", ans);}return 0;
}

#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 + 永久标记主席树)相关推荐

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

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

  2. LOJ#6072. 「2017 山东一轮集训 Day5」苹果树 解题报告

    LOJ#6072. 「2017 山东一轮集训 Day5」苹果树 解题报告 好苹果会组成连通块,整棵树的权值为 ∑ i = 1 n c i [ c i ≥ 0 ] [ s i z n u m ( c i ...

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

    Loj #6077. 「2017 山东一轮集训 Day7」逆序对 Solution 令fi,jf_{i,j}fi,j​表示前iii个数产生jjj个逆序对的方案数,每次考虑把i+1i+1i+1加入,有i ...

  4. 容斥问卷调查反馈——Co-prime,Character Encoding,Tree and Constraints,「2017 山东一轮集训 Day7」逆序对

    文章目录 Co-prime source solution code Character Encoding source solution code Tree and Constraints sour ...

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

    LOJ#6074. 「2017 山东一轮集训 Day6」子序列 先考虑全局询问怎么做,设 f ( i , c ) f(i,c) f(i,c) 表示在 S 1 ⋯ i S_{1\cdots i} S1⋯ ...

  6. LOJ#6103. 「2017 山东二轮集训 Day2」第一题 解题报告

    LOJ#6103. 「2017 山东二轮集训 Day2」第一题 解题报告 前置知识:闭区间上的连续函数的零点存在性定理: 我们定义这样的函数: 定义域为 [ l , r ] ∩ Z [l,r]\cap ...

  7. LOJ6079「2017 山东一轮集训 Day7」养猫

    养ImmortalCO k可重区间问题 的增强版:有上下界! 直接都选择s[i],然后再把一些调整到e[i] 考虑通过最大流的"最大",使得至少每k个有me个e, 通过最大流的&q ...

  8. [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]

    题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...

  9. 「2017 山东一轮集训 Day2」Pair (霍尔定理+线段树)

    题目描述 给出一个长度为  的数列  和一个长度为  的数列 ,求  有多少个长度为  的连续子数列能与  匹配. 两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对 ...

最新文章

  1. do还是doing imagine加to_中学必背英语短语集合:54个doing动名词的固定搭配
  2. 同步代码时忽略maven项目 target目录
  3. DM6467T开发板领航——开发环境
  4. 关于python保存再打开后的中文乱码的问题
  5. 如何学习Android系统源码
  6. android信鸽推送demo_腾讯信鸽Android推送集成全解
  7. python爬虫与反爬虫
  8. ideaIU-2020.3.2安装教程以及导入第一个spring boot项目运行和环境配置教程
  9. arcgis api 4.X 比例尺的添加
  10. 谁说程序员年龄大了,就没出路了?
  11. 全球最顶级的管理模式全在这了
  12. [益智]:空姐分配物品
  13. 提高网站打开速度的7大秘诀
  14. Linux线程条件控制实现线程的同步pthread_cond_init、pthread_cond_destroy、pthread_cond_wait、pthread_cond_signal
  15. pushplus 开放接口文档
  16. 想要风投被你的融资 PPT 打动吗?别忘了你其实就是在想方设法卖出自己公司的部分股权...
  17. 上阳MSN手机客户端测试版(README)
  18. 金仓数据库 KingbaseGIS 使用手册(6.11. 空间关系函数)
  19. JavaScript的eval()方法的使用
  20. 采用面向对象方法开发软件,通常需要建立三种形式的模型

热门文章

  1. redis php方案,Redis三种部署方案图文详解
  2. 理科都要学大学计算机吗,女生不适合学理科专业?报考这些理科专业,一毕业就会遭到疯抢!...
  3. java list 初始化_Java新特性:数据类型可以扔掉了?
  4. 阿基米德椭圆规原理,你看懂了吗?
  5. 这才是老公的正确用法,不吃就往死里打......
  6. 绝对不能错过!2009~2019 高中数学联赛11年真题解析
  7. 别太贪婪,这些技能能让你一辈子满足
  8. 如何把朋友升级成情侣?| 今日最佳
  9. 阿里日均纳税超1.4亿;AI换脸骗过美侦查;日本民众哄抢令和报纸;辟谣教学楼发现大量金矿;上海拨通首个5G通话;这就是今日大新闻...
  10. linux 文档属于apache,Apache 安装和使用文档