luogu6748 Fallen Lord 题解

\(\texttt{analysis}\)

发现每条边 \((x,y)\) 的权值只可能是 \(a_x\)\(a_y\)\(m\)

对于一个节点 \(x\),与它相连的所有边权的中位数不超过 \(a_x\),那么 \(deg_x\) 条边中,最多有 \(\lfloor \frac{deg_x}{2} \rfloor + 1\) 条边小于等于 \(a_x\),也就是至多有 \(\lceil \frac{deg_x}{2} \rceil - 1\) 条边权大于 \(a_x\)。设其为 \(t\)

\(f(x,0/1)\) 表示以 \(x\) 为根的子树的最大价值,其中 \((x,fa_x)\) 的权值是小于等于还是大于 \(a_x\)

对于 \(f(x,0)\),在 \(x\) 连向子节点的边中,最多可以有 \(t\) 条边大于 \(a_x\)。对于 \(f(x,1)\),这样的边数为 \(t-1\)

考虑 \(x\) 的子节点 \(y\),分类讨论一下其对 \(0\)\(1\) 状态的贡献 \(g_{0/1}\),那么 \(f(x,0)\) 能取 \(t\)\(g_1\)\(f(x,1)\)\(1\) 个。 \[ g_0 = \begin{cases} \max\Big(f(y,0)+a_y, f(y,1)+a_x\Big) & a_y \le a_x \\ \max\Big(f(y,0)+a_x, f(y,1)+a_x \Big) & a_y > a_x \end{cases} \]

\[ g_1 = \begin{cases} \max\Big(f(y,0)+a_y, f(y,1)+m \Big) & a_y \le a_x \\ \max\Big( f(y,0)+a_y, f(y,1)+m \Big) & a_y > a_x \end{cases} \]

能发现 \(g1 \ge g_0\),因此先求 \(g_0\) 的和,把 \(g_1-g_0\) 扔进一个优先队列里面,换出最大的几个 \(g_1\) 即可。

特别的,当 \(t=0\) 时,\(f(x,1) = -\infty\)

答案是 \(\max \Big( f(1,0),f(1,1)\Big)\)

\(\texttt{code}\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define uint unsigned long long 
#define SET(a,b) memset(a,b,sizeof(a))
#define CPY(a,b) memcpy(a,b,sizeof(b))
#define rep(i,j,k) for(int i=(j);i<=(k);++i)
#define per(i,j,k) for(int i=(j);i>=(k);--i)
int read() {
	int a=0, f=1; char c=getchar();
	while(!isdigit(c)) {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(isdigit(c)) a=a*10+c-'0', c=getchar();
	return a*f;
}
const int N=5e5+5;
int n, m, a[N], deg[N], f[N][2], s[N], g[N];
vector<int> p[N];
#define pb emplace_back
void dfs(int x,int fa) {
	int dlt=0, t=(deg[x]+1)/2-1;
	priority_queue<int> q;
	for(auto y:p[x]) if(y!=fa) {
		dfs(y,x);
		int g0=max(f[y][0]+min(a[x],a[y]),f[y][1]+a[x]);
		int g1=max(f[y][0]+a[y],f[y][1]+m);
		dlt+=g0;
		q.push(g1-g0);
	}
	f[x][0]=f[x][1]=dlt;
	for(int i=1;i<=t;++i) {
		int z=q.top(); q.pop();
		f[x][0]+=z;
		if(i!=t) f[x][1]+=z;
        // 这个最好循环到t,特判i!=t时不给f[x][1]
        // 为了避免t=0和1时f[x][0]没有被修改
	}
	if(!t) f[x][1]=-1e15;
}
signed main() {
	n=read(), m=read();
	rep(i,1,n) a[i]=read();
	rep(i,2,n) {
		int x=read(), y=read();
		++deg[x], ++deg[y];
		p[x].pb(y), p[y].pb(x);
	}
	dfs(1,0);
	printf("%lld\n",max(f[1][0],f[1][1]));
}

luogu6748 Fallen Lord 题解
https://yozora0908.github.io/2022/lg6748-solution/
作者
yozora0908
发布于
2022年10月23日
许可协议