首页 > 其他分享 >题解:AT_abc298_h [ABC298Ex] Sum of Min of Length

题解:AT_abc298_h [ABC298Ex] Sum of Min of Length

时间:2024-05-03 18:33:05浏览次数:24  
标签:return Min dep 题解 Sum dsum int sum define

分析

模拟赛签到题。

考虑分讨。分两种情况:

  1. \(L=R\)。
  2. \(L \ne R\)。

对于第 \(1\) 种情况,用换根 DP 求一个 \(i\) 为根时所有点的深度和就行。

对于第 \(2\) 种情况,钦定 $dep_R \ge dep_L $。

很显然,\(R\) 为根的子树中所有点都是离 \(R\) 更近。假设在 \(L\) 到 \(R\) 的路径上,除开 \(L,R\) 的某个点为 \(K\)。那么 \(K\) 的任何一个不在路径上的儿子 \(W\) 为根的子树中的所有点的贡献都是 \(dist_{i \to W}+dist_{W \to K}+\min(dist_{K\to L},dist_{K\to R})\)。前面两项是定值,而后面一项选择的分界点一定是在 \(L\) 到 \(R\) 的路径上的中点。

那么就很显然了。令中点为 \(M\),则 \(M\) 为根的子树中所有点的贡献都为 \(dist_{i \to R}\),其余所有点都为 \(dist_{i\to L}\)。

定义 \(dsum_i\) 表示 \(i\) 为根时所有点的深度和,\(sum_i\) 表示 \(i\) 为根子树中所有点到 \(i\) 的距离和,\(siz_i\) 表示 \(i\) 为根子树的大小。

根据容斥,\(dsum_R-(dsum_M-sum_M+(dep_R-dep_M)\times(n-siz_M))\) 就可以求出来 \(M\) 为根的子树中所有点到 \(R\) 的距离和。\(dsum_M-sum_M\) 将除 \(M\) 为根子树外所有点到 \(M\) 的距离,而 \(dsum_R\) 中也有这个,但每一个不在 \(M\) 子树中的点距 \(R\) 的距离都会比距 \(M\) 的距离多 \(dep_R-dep_M\),所以 \(dsum_M-sum_M+(dep_R-dep_M)\times(n-siz_M)\) 减掉了 \(M\) 为根子树外的点到 \(R\) 的距离和。

然后距离 \(L\) 更近的那些点,和 \(R\) 的情况差不多。通过 \(dsum_L,sum_M,siz_M\) 容斥即可。结果是:\(dsum_L-(sum_M+siz_M\times dist_{M\to L})\)。

复杂度 \(O(n \log n)\)。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register
#define il inline
#define pii pair<int,int>
#define x first
#define y second
#define gc getchar()
#define rd read()
#define debug() puts("------------")

namespace yzqwq{
	il int read(){
		int x=0,f=1;char ch=gc;
		while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc;}
		while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=gc;
		return x*f;
	}
	il int qmi(int a,int b,int p){
		int ans=1;
		while(b){
			if(b&1) ans=ans*a%p;
			a=a*a%p,b>>=1;
		}
		return ans;
	}
	il auto max(auto a,auto b){return (a>b?a:b);}
	il auto min(auto a,auto b){return (a<b?a:b);}
	il int gcd(int a,int b){
		if(!b) return a;
		return gcd(b,a%b);
	}
	il int lcm(int a,int b){
		return a/gcd(a,b)*b;
	}
	il void exgcd(int a,int b,int &x,int &y){
		if(!b) return x=1,y=0,void(0);
		exgcd(b,a%b,x,y);
		int t=x;
		x=y,y=t-a/b*x;
		return ;
	}
	mt19937 rnd(time(0));
}
using namespace yzqwq;
#define D(x,y) ((dep[x]+dep[y]-2*dep[lca(x,y)]))

const int N=2e5+10,M=20;
int n,m;
int ne[N<<1],e[N<<1],h[N],idx;
int dep[N],f[N][M],siz[N];
int sum[N];//i子树中与i的距离和
int dsum[N];//i为根时的距离和 

il void add(int a,int b){
	ne[++idx]=h[a],e[idx]=b,h[a]=idx;
	ne[++idx]=h[b],e[idx]=a,h[b]=idx;
}
il void dfs(int now,int fa){
	dep[now]=dep[fa]+1,siz[now]=1,f[now][0]=fa;
	for(re int i=1;i<M;++i) f[now][i]=f[f[now][i-1]][i-1];
	for(re int i=h[now];i;i=ne[i]){
		int j=e[i];if(j==fa) continue;
		dfs(j,now);
		siz[now]+=siz[j];
		sum[now]+=sum[j]+siz[j];
	}
	return ;
}
il void dfs2(int now,int fa){
	for(re int i=h[now];i;i=ne[i]){
		int j=e[i];if(j==fa) continue;
		dsum[j]=dsum[now]-siz[j]+(n-siz[j]);
		dfs2(j,now);
	}
	return ;
}
il int lca(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	for(re int i=19;i>=0;--i) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
	if(x==y) return x;
	for(re int i=19;i>=0;--i) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
il int up(int x,int y){
	int now=0;
	while(y){
		if(y&1) x=f[x][now];
		y>>=1,++now;
	}
	return x;
}

il void solve(){
	n=rd;
	for(re int i=1,a,b;i<n;++i)
		a=rd,b=rd,add(a,b);
	dfs(1,0),dsum[1]=sum[1],dfs2(1,0);
	m=rd;
	for(re int i=1;i<=m;++i){
		int l=rd,r=rd;
		if(dep[l]>dep[r]) swap(l,r);
		if(l==r) printf("%lld\n",dsum[l]);
		else{
			int ans=0,dis=D(l,r)-1;
			int m_=up(r,dis/2);//中点 
			ans+=dsum[r]-(dsum[m_]-sum[m_]+(dep[r]-dep[m_])*(n-siz[m_]));//离R近的 
			ans+=dsum[l]-(sum[m_]-siz[m_]*D(m_,l));//离L近的 
			printf("%lld\n",ans);
		}
	}
	return ;
}

signed main(){
// 	freopen("sum.in","r",stdin);
// 	freopen("sum.out","w",stdout);
	int t=1;while(t--)
	solve();
	return 0;
}

标签:return,Min,dep,题解,Sum,dsum,int,sum,define
From: https://www.cnblogs.com/harmisyz/p/18171475

相关文章

  • 题解【[ABC077D] Small Multiple】
    题目链接题意简述:给定正整数\(K\),求数位之和最小的\(K\)的倍数的数位和。错误方向:\(K\)的倍数一定满足\(K\timesS\),根据\(K\)的特征构造出合适的\(S\)。正确方向考虑直接构造出K的倍数,由于从1开始可以通过×10和+1构造出所有数字,并且在此......
  • 【题解】P4711 「化学」相对分子质量
    Problem给定一个长度为\(L\)的化学式,求出此化学式的相对分子质量。例:十二水合硫酸铝钾(明矾)\(KAl(SO_4)_2\cdot12H_2O\).输入格式形为:KAl(SO_{4})_{2}~12H_{2}OSolve清新小模拟。定义一下“结账”这个概念,分为三种:原子结账,即为当单独的一个(一坨)原子计算完成后,计入所属......
  • [题解]ABC337E Bad Juice
    ABC337EBadJuice一开始的想法如下:就是利用二分法,对于一个区间\([l,r]\),分成\([l,mid-1],[mid,r-1]\)两部分,各找两个朋友喝,右边还空出一个\(r\),如果前面两个朋友都没中毒,那说明\(r\)这瓶有毒。但仔细一想,我们发现\([1,n)\)的瓶子中任意一个我们分出的区间\([l,r]\),都用去了\(......
  • 题解:CF607E Cross Sum
    Problem给定\(N\)条不平行的直线\(y=\frac{k_i}{1000}x+\frac{b_i}{1000}\),\(N\)条直线总共会有\(\frac{N(N-1)}{2}\)个交点(包含在同一个位置的点,即相同位置算不同的点),找出距离原点前\(K\)近的交点的距离和。$2\leN\le5\times10^4$,\(1\leK\le\frac{N(N-1)}{2}\)......
  • P6123 [NEERC2016] Hard Refactoring 题解
    本题说白了,就是一道big模拟!!!题意不再赘述,我们直接看思路。这里作者借鉴了某差分思想:末尾加空格,用于判断最后一个条件;若只有\(\le\),对给出的数字和数组第一个进行标记。标记的时候要+32769,因为数组中不存在负数下标,以免越界;若只有\(\ge\),就标记给出的数字和数组最后......
  • 5.2考试题解
    T1[NOIP2017提高组]时间复杂度大模拟……#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intt,n,k,as,nw,tr,ed[105];intc[26],str[105],b[105];stringtim;stack<int>st;structAadd{strings,t,fr,ed;}ad[105];intdfs(intx){i......
  • P4921 题解
    linkHint:错排计数。\(ans_k=C_n^k\timesA_n^k\times2^k\timesg(n-k)\)\(g(i)\)代表\(i\)对情侣全部错开的方案数。解释一下\(ans_k\)的表达。我们从\(n\)对情侣中无序地抽出\(k\)对情侣,有序地放到\(k\)排座位上,这里的方案数是\(C_n^k\timesA_n^k\)。由于两个......
  • 解决vscode连接远程服务器出现Bad owner or permissions on C:\\Users\\Administr
    1.找到.ssh文件夹。它通常位于C:\Users2.右键单击.ssh文件夹,然后单击“属性”,选择“安全”3.单击“高级”。单击“禁用继承”,单击“确定”。将出现警告弹出窗口。单击“从此对象中删除所有继承的权限”。4.此时所有用户都将被删除。添加所有者。在同一窗口中,单击“编辑”按......
  • UVA1362 Exploring Pyramids 题解
    题目传送门前置知识欧拉序|区间DP|乘法原理解法DFS序可近似理解为欧拉序,故考虑区间DP。设\(f_{l,r}\)表示\([l,r]\)对应的二叉树的个数,状态转移方程为\(f_{l,r}=\begin{cases}1&l=r\\[s_{l}=s_{r}]\times\sum\limits_{i=l+2}^{r}[s_{l}=s_{i}]\timesf_{......
  • Educational Codeforces Round 165 (Rated for Div. 2) C. Minimizing the Sum题解
    题意CodeforcesRound809(Div.2)D1.ChoppingCarrots(EasyVersion)给你两个整数\(n(1\len\le3e5),k(0\lek\le10)\),一个数组\(a(1\lea_i\le10^9)\)。你可以进行如下操作最多\(k\)次:选定一个数\(i(1\lei\len)\),让其变为相邻的数(变为\(a_{i-1},a_{i......