ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)

2021-06-05 10:02:46  阅读:176  来源: 互联网

标签:return 剖分 fa loj top Day5 int fi mod


题意

题目链接

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;
}

标签:return,剖分,fa,loj,top,Day5,int,fi,mod
来源: https://blog.51cto.com/u_15239936/2868842

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有