Balancing a Tree (USACO Gold 2022 US Open)
这是一个比较考思维能力的数学不等式题。
- 从题目测试点描述,可以猜到一长串的形状是重要的,把这个拿出来仔细看。可以得到以下结论,对于一串节点,最小化的平衡度为:
这个意思就是说,一串节点上面,最优情况下最右侧点的取值受限制(最小值),而最左侧点的取值受限制(最大值)。
- 再看整个树,这时候每一个节点对最后范围的影响,除了从开始到根这个一串节点如上面的公式计算之外,整棵树还存在最右侧节点和最左侧节点,这时候还会导致不平衡度至少为这个范围的一半。
- 的时候要输出一个方案,这个就是所有值都向这个中点靠拢就可以了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
int n; // 2e5
int p[200005], l[200005], r[200005], L[200005], R[200005], L2, R2;
int T,B;
int ans;
const int INF = 1e9;
int main() {
scanf("%d %d", &T, &B);
while (T--) {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
scanf("%d", &p[i]);
p[i]--;
}
ans = 0;
L2 = INF, R2 = -INF;
for (int i = 0; i < n; i++) {
scanf("%d %d", &l[i], &r[i]);
L[i] = r[i]; R[i] = l[i];
if (i) {
L[i] = min(L[p[i]], L[i]);
R[i] = max(R[p[i]], R[i]);
}
L2 = min(L2, r[i]);
R2 = max(R2, l[i]);
ans = max(ans, R[i]-L[i]);
}
ans = max(ans, (R2-L2+1)/2);
int mid = (L2+R2)/2;
printf("%d\n", ans);
if (B)
for (int i = 0; i < n; i++)
printf("%s%d", i ? " " : "", r[i] < mid ? r[i] : l[i] > mid ? l[i] : mid);
printf("\n");
}
return 0;
}