[POI2014] HOT-Hotels

前言

长剖板题,但是我实在懒得讲了,就直接贴代码了。

代码下部有少量讲解。

题目

洛谷

DarkBZOJ 加强版

代码

//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;

typedef long long LL;
const int MAXN = 100005;
int n;

LL Read()
{
	LL x = 0,sg = 1; char c = getchar();
	while(c > '9' || c < '0') {if(c == '-') sg = -1;c = getchar();}
	while(c >= '0' && c <= '9') {x = (x*10) + (c^48);c = getchar();}
	return x * sg;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x,T y){return x < 0 ? -x : x;}

int head[MAXN],tot;
struct edge{
	int v,nxt;
}e[MAXN<<1];
void Add_Edge(int u,int v){
	e[++tot] = edge{v,head[u]};
	head[u] = tot;
}
void Add_Double_Edge(int u,int v) {
	Add_Edge(u,v);
	Add_Edge(v,u);
}

int son[MAXN],len[MAXN];
void dfs1(int x,int fa){
	for(int i = head[x],v; i ;i = e[i].nxt){
		if((v = e[i].v) == fa) continue;
		dfs1(v,x);
		if(len[v] > len[son[x]]) son[x] = v;
	}
	len[x] = len[son[x]] + 1;
}
LL tmp[MAXN<<2],*f[MAXN],*g[MAXN],*ID = tmp,ans;
void dfs2(int x,int fa){
	f[x][0] = 1;
	if(!son[x]) return;
	f[son[x]] = f[x]+1,g[son[x]] = g[x]-1,dfs2(son[x],x); 
	ans += g[x][0];
	for(int i = head[x],v; i ;i = e[i].nxt){
		if((v = e[i].v) == fa || v == son[x]) continue;
		f[v] = ID; ID += len[v]<<1;
		g[v] = ID; ID += len[v]<<1;
		dfs2(v,x);
		for(int j = 0;j < len[v];++ j) {
			if(j) ans += f[x][j-1] * g[v][j];
			ans += g[x][j+1] * f[v][j];
		}
		for(int j = 0;j < len[v];++ j){
			g[x][j+1] += f[x][j+1] * f[v][j];
			f[x][j+1] += f[v][j];
			if(j) g[x][j-1] += g[v][j];
		}
	}
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read();
	for(int i = 1;i < n;++ i) Add_Double_Edge(Read(),Read());
	dfs1(1,0);
	f[1] = ID; ID += len[1]<<1; 
	g[1] = ID; ID += len[1]<<1;
	dfs2(1,0);
	Put(ans,'\n');
	return 0;
}
/*
淦,以前长剖竟然一直没学懂,指针都不会 
f[x][i] 表示x子树内到x距离为i的点个数
g[x][i] 表示x子树内(u,v) 到 lca(u,v) 的距离为dis,lca(u,v)到 x的距离为 dis-i的点对个数 
继承长儿子状态用指针,这个是基础知识...
*/
posted @ 2022-04-14 11:42  皮皮刘  阅读(69)  评论(0编辑  收藏  举报