「2017 山东一轮集训 Day5」距离
/*
写完开店再写这个题目顿时神清气爽, 腰也不疼了, 眼也不花了
首先考虑将询问拆开, 就是查询一些到根的链和点k的关系
根据我们开店的结论, 一个点集到一个定点的距离和可以分三部分算
那么就很简单了吧QAQ, 在树上可持久化弄一下
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#define ll long long
#define mmp make_pair
#define M 200010
using namespace std;
int read()
{
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
int type, n, q, sz[M], son[M], fa[M], top[M], dfn[M], ver[M], dft, cnt, p[M], deep[M];
ll dis[M], sum[M], w[M], ans;
vector<pair<int,int> > to[M];
int lc[20000100], rc[20000100], v[20000100], rt[M];
ll t[20000100];
void dfs(int now, int f)
{
deep[now] = deep[f] + 1;
sz[now] = 1;
fa[now] = f;
for(int i = 0; i < to[now].size(); i++)
{
int vj = to[now][i].first, v = to[now][i].second;
if(vj == f) continue;
dis[vj] = dis[now] + v;
ver[vj] = v;
// deep[vj] = deep[now] + 1;
dfs(vj, now);
if(sz[vj] > sz[son[now]]) son[now] = vj;
sz[now] += sz[vj];
}
}
void dfs(int now)
{
dfn[now] = ++cnt;
w[cnt] = ver[now];
if(son[now])
{
top[son[now]] = top[now];
dfs(son[now]);
}
for(int i = 0; i < to[now].size(); i++)
{
int vj = to[now][i].first;
if(vj == fa[now] || vj == son[now]) continue;
top[vj] = vj;
dfs(vj);
}
}
void modify(int last, int &now, int l, int r, int ln, int rn)
{
now = ++cnt;
lc[now] = lc[last], rc[now] = rc[last], t[now] = t[last], v[now] = v[last];
if(l == ln && r == rn)
{
v[now]++;
return;
}
t[now] += w[rn] - w[ln - 1];
int mid = (l + r) >> 1;
if(ln > mid) modify(rc[last], rc[now], mid + 1, r, ln, rn);
else if(rn <= mid) modify(lc[last], lc[now], l, mid, ln, rn);
else modify(lc[last], lc[now], l, mid, ln, mid), modify(rc[last], rc[now], mid + 1, r, mid + 1, rn);
}
ll query(int now, int l, int r, int ln, int rn)
{
ll ans = 1ll * (w[rn] - w[ln - 1]) * v[now];
if(l == ln && r <= rn) return ans + t[now];
int mid = (l + r) >> 1;
if(rn <= mid) return ans + query(lc[now], l, mid, ln, rn);
else if(ln > mid) return ans + query(rc[now], mid + 1, r, ln, rn);
else return ans + query(lc[now], l, mid, ln, mid) + query(rc[now], mid + 1, r, mid + 1, rn);
}
void Modify(int &now, int x)
{
for(; top[x] != 1; x = fa[top[x]]) modify(now, now, 1, n, dfn[top[x]], dfn[x]);
modify(now, now, 1, n, dfn[1], dfn[x]);
}
void work(int now)
{
rt[now] = rt[fa[now]];
Modify(rt[now], p[now]);
sum[now] = dis[p[now]] + sum[fa[now]];
for(int i = 0; i < to[now].size(); i ++)
{
int vj = to[now][i].first;
if(vj == fa[now]) continue;
work(vj);
}
}
ll Query(int x, int k)
{
if(k == 0) return 0;
// cout << k << " ";
ll ans = sum[x];
ans += dis[k] * deep[x];
for(; top[k] != 1; k = fa[top[k]]) ans -= 2ll * query(rt[x], 1, n, dfn[top[k]], dfn[k]);
ans -= 2ll *query(rt[x], 1, n, dfn[1], dfn[k]);
// cout << x << " " << ans << "!!!!!!!\n";
return ans;
}
int LCA(int a, int b)
{
while(top[a] != top[b])
{
if(deep[top[a]] < deep[top[b]]) swap(a, b);
a = fa[top[a]];
}
if(deep[a] > deep[b]) swap(a, b);
return a;
}
int main()
{
type = read();
n = read(), q = read();
for(int i = 1; i < n; i++)
{
int vi = read(), vj = read(), v = read();
to[vi].push_back(mmp(vj, v));
to[vj].push_back(mmp(vi, v));
}
for(int i = 1; i <= n; i++) p[i] = read();
dfs(1, 0);
top[1] = 1;
dfs(1);
for(int i = 1; i <= n; i++) w[i] += w[i - 1];
work(1);
while(q--)
{
ll vi = read() ^ ans, vj = read() ^ ans, k = read() ^ ans;
int l = LCA(vi, vj);
ans = Query(vi, k) + Query(vj, k) - Query(l, k) - Query(fa[l], k);
cout << ans << "\n";
ans *= type;
}
return 0;
}
「2017 山东一轮集训 Day5」距离的更多相关文章
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)
题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(费用流)
题意 题目链接 Sol 我们可以把图行列拆开,同时对于行/列拆成很多个联通块,然后考虑每个点所在的行联通块/列联通块的贡献. 可以这样建边 从S向每个行联通块连联通块大小条边,每条边的容量为1,费用为 ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
- 「2017 山东一轮集训 Day5」字符串 (后缀自动机, 拓扑排序)
/** 首先通过SAM求出每个串本质不同的子串 然后发现转移不好处理整体的本质不同 形如串A可能状态有a,b,ab,空,串B可能状态有b,空两种, 那么我们需要处理ab + 空 和 a + b的情况 ...
- 「2017 山东一轮集训 Day5」字符串
题目 比较神仙的操作啊 首先先考虑一个串的做法,我们有两种:SA或SAM,其中SAM又有两种,拓扑图上的\(dp\)和\(parent\)上随便统计一下 显然这道题\(SA\)和\(parent\)树 ...
- LOJ6071. 「2017 山东一轮集训 Day5」字符串 [SAM]
LOJ 思路 这种计数题显然是要先把每一个合法的串用唯一的方法表示出来.(我连这都没想到真是无可救药了) 如何唯一?容易想到把前缀尽可能多地在第一个串填掉,然后填第二个,第三个-- 如何做到这样?可以 ...
- 题解 「2017 山东一轮集训 Day5」苹果树
题目传送门 题目大意 给出一个 \(n\) 个点的图,每个点都有一个权值 \(f_i\) ,如果 \(f_i=-1\) 表示 \(i\) 这个点是坏的.定义一个点是有用的当且仅当它不是坏的,并且它连的 ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
随机推荐
- 3、eclipse集成svn
手动安装 1.从官网下载适合自己开发工具的site-.zip文件,网址是:subclipse.tigris.org,2.从中解压出features与plugins文件夹,复制到eclipse的目录my ...
- CF 666E Forensic Examination——广义后缀自动机+线段树合并
题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...
- eclipse卡死在search for main types 20 files to index
run as application时,提示search for main types 20 files to index (*/*/*.jar)某个maven依赖jar出了问题,找不到main方法 ...
- 学习笔记: jstack与线程状态
jstatck可以打印JVM内部所有线程 1.查看有哪些java进程 2.查看所有线程的信息 重定向到5579.txt文件中 jstack 5579 > 5579.txt 3.线程的状态 New ...
- Flume 概述+环境配置+监听Hive日志信息并写入到hdfs
Flume介绍Flume是Apache基金会组织的一个提供的高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据:同时,Flume提供 ...
- SQL 更新修改删除一个表,库存自动增减的写法
create trigger tri_asbon asb for insert as begin declare @rk int declare @ck int declare @sid varcha ...
- Java消息机制 ActiveMQ入门实例
转载自:http://www.cnblogs.com/wyh3721/p/5917316.html 1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ ...
- SpringBoot+Maven 多模块项目的构建、运行、打包
SpringBoot+Maven 多模块项目的构建.运行.打包 https://blog.csdn.net/zekeTao/article/details/79413919
- 修改postfix smtp端口,防止公网扫描浪费你的服务器流量
邮件服务器的默认发送邮件端口是25,一些ISP会封锁25端口防止垃圾邮件的发送,这样就导致不能使用Foxmail.outlook等邮件客户端发送邮件.修改默认smtp端口就可以解决这个问题.下面的方法 ...
- ecstore-ftp设置,不能上传文件
某些主机居然不能上传,ftp改成127.0.0.1即可 ftp地址改成127.0.0.1即可...