专栏文章

题解:CF1693B Fake Plastic Trees

CF1693B题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mind7v8b
此快照首次捕获于
2025/12/02 00:30
3 个月前
此快照最后确认于
2025/12/02 00:30
3 个月前
查看原文

CF1693B Fake Plastic Trees 题解

  • 首先,对于一条路径,从根走到叶子节点明显更优(对于使操作次数更少来说)。
  • 对于叶子节点 vvlvavrvl_v \leq a_v \leq r_v,我们使对应的 cv=rvc_v = r_v 肯定是不劣的。
  • 对于 vv 的父节点 uu(或任意非叶子节点),vv 的贡献也一定会累加到 uu(因为到 vv 必须经过 uu),则有 maxcuvsonuvmaxcv\max \sum {c_u} \le \sum_{v \in son_u}^{v} \max \sum c_v
  • 我们可以设 vsonumaxcv\sum_{v \in son_u} \max \sum c_vsumsum,所以可以进行分类讨论:
  1. 对于 sum<lu sum<l_u,可以把 uu 当作叶子节点再进行一次操作,使 au=rua_u=r_u
  2. 对于 sum[lu,ru]sum \in [ l_u,r_u ],直接返回。
  3. 对于 sum>rusum > r_u,修改 aia_i。 使 au=ru au=r_u 后返回。
  • 最后 dfs,递归解决 QwQ。
codeCPP
#include<bits/stdc++.h>
#define il inline
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
il ll read(){
	ll x=0;bool f=0;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=1;ch=getchar();}
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
il void write(ll x){
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10|48);
}
const int N=2e5+5;
vector<int> g[N];
int l[N],r[N];
ll ans=0;
il ll dfs(int u){
	if(g[u].empty()) {++ans;return r[u];}
	ll sum=0;
	for(int v:g[u]) sum+=dfs(v);
	if(sum<l[u]) {++ans;return r[u];}
	return min(sum,(ll)r[u]);
}
il void solve(){
	int n=read();ans=0;
	for(int i=1;i<=n;++i) g[i].clear();
	for(int i=2,x;i<=n;++i) cin>>x,g[x].push_back(i);
	for(int i=1;i<=n;++i) cin>>l[i]>>r[i];
	dfs(1);
	write(ans);putchar('\n');
}
int main()
{
	int T=read();
	while(T--) solve();
	return 0;
}
完结撒花。

评论

1 条评论,欢迎与作者交流。

正在加载评论...