首页 > 其他分享 >【思维】【DP】ABC298Ex Sum of Min of Length 题解

【思维】【DP】ABC298Ex Sum of Min of Length 题解

时间:2023-10-05 22:44:53浏览次数:39  
标签:dep dist Min int 题解 Sum cin fa now

ABC298Ex

简单题。

因为有 \(\min\) 不好做,容易想到讨论 \(d(i, L)\) 和 \(d(i, R)\) 的大小。

令 \(p = \text{LCA}(L, R)\),\(dep_L > dep_R, dist = dep_L + dep_R - 2\times dep_p\),\(now\) 满足 \(dep_L - dep_{now} = \lfloor\dfrac{dist}{2}\rfloor\)

则 \(L\) 一定在 \(now\) 的子树内,且对于 \(\forall i\in \{\text{subtree}(now)\}\) 时均有 \(d(i, L) \le d(i, R)\),否则 \(d(i, L) > d(i, R)\)。其中 \(\text{subtree}(x)\) 表示 \(x\) 的子树。

容易想到求一个点到其他点的距离和。

令 \(val_i\) 表示 \(\sum\limits_{j = 1}^{n} d(i, j)\)。

在 dfs 时处理一下即可,显然可以做到 \(\mathcal{O}(n)\)。

最后再将 \(dist\) 奇偶讨论一下即可。

时间复杂度:\(\mathcal{O}(n + m\log n)\),可以使用线性 LCA 做到 \(\mathcal{O}(n + m)\)

代码:

const int N = 2e5 + 10;
int n, m;
int siz[N], d[N], fa[N][20];
ll dis[N], v[N];
vector<int> e[N];

void dfs1(int u, int f) {
	d[u] = d[f] + 1, siz[u] = 1, fa[u][0] = f;
	for (int i = 1; i <= 18; i++)
		fa[u][i] = fa[fa[u][i - 1]][i - 1];
	for (int v : e[u])
		if (v != f) {
			dfs1(v, u);
			siz[u] += siz[v];
			dis[u] += dis[v] + siz[v];
		}
}
void dfs2(int u, int f) {
	if (u == 1)
		v[u] = dis[u];
	else
		v[u] = v[f] + (siz[1] - siz[u]) - siz[u];
	for (int v : e[u])
		if (v != f)
			dfs2(v, u);
}
int lca(int u, int v) {
	if (d[u] < d[v])
		swap(u, v);
	for (int i = 18; i >= 0; i--)
		if (d[fa[u][i]] >= d[v])
			u = fa[u][i];
	if (u == v)
		return u;
	for (int i = 18; i >= 0; i--)
		if (fa[u][i] != fa[v][i])
			u = fa[u][i], v = fa[v][i];
	return fa[u][0];
}
int tonode(int u, int st) {
	for (int i = 18; i >= 0; i--)
		if (st >> i & 1)
			u = fa[u][i];
	return u;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n;
	for (int i = 1, u, v; i < n; i++) {
		cin >> u >> v;
		e[u].pb(v), e[v].pb(u);
	}
	dfs1(1, 0), dfs2(1, 0);
	cin >> m;
	while (m--) {
		int l, r;
		cin >> l >> r;
		if (d[l] < d[r])
			swap(l, r);
		int p = lca(l, r), dist = d[l] + d[r] - 2 * d[p];
		if (dist % 2 == 0) {
			int now = tonode(l, dist / 2);
			cout << v[l] + v[r] - v[now] - 1ll * n * dist / 2 << "\n";
		} else {
			int now = tonode(l, dist / 2);
			cout << v[l] + v[r] - v[now] - 1ll * n * (dist / 2) - siz[now] << "\n";
		}
	}
	return 0;
}

标签:dep,dist,Min,int,题解,Sum,cin,fa,now
From: https://www.cnblogs.com/Pengzt/p/17744064.html

相关文章

  • 【图论】【寻找性质】CF1151E Number of Components 题解
    CF1151E发现每一个\(f(l,r)\)中的连通块总是一条链(一棵树)。那么此时连通块的数量就等于点的数量减去边的数量。先考虑点的总数,一个价值为\(a_i\)的点一定是在\(l\leqslanta_i\)且\(r\geqslanta_i\)的\(f(l,r)\)中才会有一个贡献,根据乘法原理,它会产生\(a_i\time......
  • 【二分】P7795 [COCI2014-2015#7] PROSJEK 题解
    P7795典。显然\(\mathcal{O}(n^2)\)的时间复杂度无法通过。使子段平均值最大,考虑二分。可以二分平均值\(mid\),然后判断是否有满足条件的子段.时间复杂度:\(\mathcal{O}(\dfrac{n\log\max\{a_i\}}{\text{eps}})\),其中\(\text{eps}\)为设置的精度,\(\max\{a_i\}\leq10......
  • P8565 Sultan Rage 题解
    P8565发现数列\(a\)增长的特别快,项数最多时是\(a_1=a_2=\cdots=a_{100}\),但这样也只会有一百多项就可以超过\(10^{18}\)。可以考虑搜索,因为搜索树会比较稀疏,函数dfs(val,cur)表示凑出\(x\)还需要\(val\),现在在考虑\(cur\)。但光是搜索肯定不能过这道题,考虑优......
  • P4133 [BJOI2012]最多的方案 题解
    P4133双倍经验发现斐波那契数列增长极快,不到\(100\)项就超过了\(10^{18}\),搜索树也极为稀疏,可以考虑搜索。爆搜肯定会超时,考虑优化:可行性剪枝。记忆化,去除重复的计算。改变搜索的顺序,因为先考虑小元素的话,会有较多的无用的搜索,且小元素较灵活,更容易凑到\(x\),故可......
  • 【竞赛图】【DP】ARC163D Sum of SCC 题解
    ARC163D发现这个竞赛图一定能被分为两个集合\(A\),\(B\)。满足\(\forallu\inA,v\inB\),均有\(u\tov\inE\)。答案就是划分这两个集合的方案数。证明:首先,竞赛图缩完点后一定是一条链,对强连通分量进行标号,满足编号小的强连通分量指向编号大的强连通分量。不妨令竞赛图\(G\)......
  • 【整除分块】【DP】ABC239Ex Dice Product 2 题解
    ABC239H简单题。令\(f_i\)表示乘到\(\gei\)的期望。容易得到\(f_i=\dfrac{\sum\limits_{j=1}^{n}f_{\lceil\frac{i}{j}\rceil}}{n}\)。将\(f_i\)移到同一边,去掉系数,有\(f_i=\dfrac{n\sum\limits_{j=2}^{n}f_{\lceil\frac{i}{j}\rceil}}{n-1}\)。提出\(\frac{n-1}{n......
  • 【字符串】【哈希】ABC284F ABCBAC 题解
    ABC284F这题的正解是\(Z\)函数。如果\(str=T+T\)的话,若可以找到连续的分别长为\(n\)的两段,且这两段可通过\(1\)次翻转变为相同的字符串,那么便一定有解,否则无解。暴力判断是\(\mathcal{O}(n)\)的,时间复杂度直接上天。可以用哈希\(\mathcal{O}(1)\)地判断出两个......
  • 【组合计数】ARC058D Iroha and a Grid 题解
    ARC058D简单组合计数。可以先把矩形旋转一下,变为求从\((1,1)\)走到\((n,m)\),只能向上或向右移动。且不经过左上角的\(A\timesB\)的禁区的方案数,对\(10^9+7\)取模。假如没有\(A\timesB\)的禁区的话,那么方案数为\(C_{n+m-2}^{n-1}\)。就是一共要走\(n+m-2\)......
  • 「题解」Codeforces Round 883 (Div. 3)
    A.EscalatorConversationsProblem[题目](RudolphandCuttheRope)Sol&Code绳子长度大于钉子高度的要剪#include<bits/stdc++.h>typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}in......
  • 「题解」Codeforces Round 888 (Div. 3)
    A.EscalatorConversationsProblem题目Sol&Code签到#include<bits/stdc++.h>typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT,n,m,k,h;intmain(){scanf(......