首页 > 其他分享 >洛谷 P9129 [USACO23FEB] Piling Papers G

洛谷 P9129 [USACO23FEB] Piling Papers G

时间:2023-11-14 10:34:47浏览次数:29  
标签:sz 遍历 洛谷 cdot Piling int 子树 为根 P9129

第一问是简单的,\(2(n - 1) - [T = 1] \cdot \max\limits_{i = 1}^{n}\{dep_i\}\)。

对于第二问:

设 \(f(u)\) 表示要求起点和终点均为 \(u\) 的情况下从 \(1\) 时刻开始遍历完以 \(u\) 为根的子树的最小花费,\(g(u)\) 表示要求起点为 \(u\),重点深度最大的情况下从 \(1\) 时刻开始遍历完以 \(u\) 为根的子树的最小花费。

令 \(s(u)\) 表示以 \(u\) 为根的子树中的 \(a\) 的和,\(sz(u)\) 表示以 \(u\) 为根的子树大小。对于 \(u\) 的两个儿子 \(v_1, v_2\),若先遍历 \(v_1\) 再遍历 \(v_2\),则它们的贡献为:

\[f(u) \gets f(v_1) + f(v_2) + 2 \cdot sz(v_1) \cdot s(v_2) \]

若交换遍历顺序,则又有:

\[f(u) \gets f(v_1) + f(v_2) + 2 \cdot sz(v_2) \cdot s(v_1) \]

也就是说,\(v_1\) 先于 \(v_2\) 遍历当且仅当 \(sz(v_1) \cdot s(v_2) \le sz(v_2) \cdot s(v_1)\)。

于是排序更新即可,这部分的时间复杂度为 \(\mathcal O(n \log n)\)。

\(g\) 借助 \(f\) 更新即可。

也就是把符合条件的 \(f(v)\) 去掉,在最后加上 \(g(v)\),具体看代码吧。

总时间复杂度 \(\mathcal O(n \log n)\)。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr int N = 2e5 + 10;

int n, T, a[N], sz[N], maxd[N];
ll s[N], f[N], g[N];

vector<int> G[N];

bool cmp(const int &a, const int &b) {
	return sz[a] * s[b] <= sz[b] * s[a];
}

void dfs(int u) {
	sz[u] = 1, s[u] = a[u];
	for (int v : G[u]) {
		dfs(v);
		maxd[u] = max(maxd[u], maxd[v] + 1), sz[u] += sz[v], s[u] += s[v];
	}
	sort(G[u].begin(), G[u].end(), cmp);
	ll time = 1, sufs = 0;
	for (int v : G[u]) f[u] += f[v] + time * s[v], time += 2 * sz[v], sufs += s[v];
	if (G[u].empty()) return;
	g[u] = 9e18;
	for (int v : G[u]) {
		time -= 2 * sz[v], sufs -= s[v];
		if (maxd[u] == maxd[v] + 1) g[u] = min(g[u], f[u] - f[v] + g[v] - 2 * sz[v] * sufs + (time - 1) * s[v]);
	}
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
	cin >> n >> T;
	for (int i = 2, fa; i <= n; i++) {
		cin >> fa >> a[i];
		G[fa].emplace_back(i);
	}
	dfs(1);
	if (T == 0) cout << 2 * (n - 1) << ' ' << f[1];
	else cout << 2 * (n - 1) - maxd[1] << ' ' << g[1];
	return 0;
}

标签:sz,遍历,洛谷,cdot,Piling,int,子树,为根,P9129
From: https://www.cnblogs.com/chy12321/p/17831050.html

相关文章

  • 洛谷P8599.带分数
    这道题可以应用数位dp的思想:既然根据限制条件算出符合条件的数很难,如同大海捞针,那我就直接拿可能用到的数字,按数位把它拼出来,反而还更快。对于这道题,三个数字就是1到9全排列的三段,我们只要对每个排列,枚举分段方式即可。#include<stdio.h>#include<algorithm>#include<ios......
  • 洛谷P8598.票据
    简单题,输入有技巧注意要在正式读入之前先用一个getline把那个回车读入了,因为cin不会处理回车。#include<iostream>#include<algorithm>#include<stdlib.h>#include<cstring>#include<sstream>usingnamespacestd;constintN=1e5+5;intt,n,a[N];strings......
  • 洛谷P8597.翻硬币
    用一个队列模拟,每次都只处理队头位置的差异#include<iostream>#include<algorithm>#include<stdlib.h>#include<cstring>usingnamespacestd;constintN=1005;chars[N],t[N];intpos[N],hh,cnt,tt;intmain(){scanf("%s%s",s......
  • 洛谷 NOIP 2023 模拟赛 T2 汪了个汪
    洛谷NOIP2023模拟赛T2汪了个汪考试建出正解图不知道怎么处理,题解区樱雪喵博客薄纱。樱雪喵题解链接Ps:笔者语文爆炸,不建议阅读本文思路首先你会发现,一共有\(\frac{n(n-1)}{2}\)个二元组,有\(\frac{n(n-1)}{2}\)个横向相邻数对。按照题目要求,一个横向数对对应一个二......
  • 231112洛谷模拟赛
    T1种树P9836种树只需要运用一些小学奥数即可解决首先需要知道的一点是将\(p_i\)质因数分解后得到\(p_i=\prod\limits_{j=1}^ma_j^{k_j}\),则有\(\prod\limits_{i=1}^{m}(k_i+1)\)个因数则最终就是把所有的都再乘起来考虑\(w\)分解后能造成什么影响,依据乘法......
  • 【洛谷 P2669】[NOIP2015 普及组] 金币 题解(循环)
    [NOIP2015普及组]金币题目背景NOIP2015普及组T1题目描述国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这......
  • 洛谷NOIP2023模拟赛
    种树题目背景小Rf不是很喜欢种花,但他喜欢种树。题目描述路边有\(n\)棵树,每棵树的高度均为正整数,记作\(p_1,p_2\dotsp_n\)。定义一棵树的宽度为它高度的正因数个数,这些树能覆盖的距离为它们宽度的乘积,你想请你的朋友们来乘凉,但你发现这些树能覆盖的距离不够多。......
  • 【洛谷 P1035】[NOIP2002 普及组] 级数求和 题解(循环)
    [NOIP2002普及组]级数求和题目描述已知:。显然对于任意一个整数,当足够大的时候,。现给出一个整数,要求计算出一个最小的,使得。输入格式一个正整数。输出格式一个正整数。样例#1样例输入#11样例输出#12提示【数据范围】对于的数据,。【题目来源】NOIP2002普及组第一题......
  • 【洛谷 P1980】[NOIP2013 普及组] 计数问题 题解(取余)
    [NOIP2013普及组]计数问题题目描述试计算在区间到的所有整数中,数字()共出现了多少次?例如,在到中,即在中,数字出现了次。输入格式个整数,之间用一个空格隔开。输出格式个整数,表示出现的次数。样例#1样例输入#1111样例输出#14提示对于的数据,,。思路求每个数字的......
  • 每日水题记录(洛谷)
    每日水题记录(洛谷)只记录红橙题,因为\(\ge\)橙不算很水的题。\(2023.11.9\)P1012[NOIP1998提高组]拼数\(75\)分代码直接把每个数字用字符串输入,然后按字典序排序。原因:不能直接按字典序排序,寄。#include<iostream>#include<algorithm>#include<cmath>#include<c......