1 条题解
-
0
自动搬运
来自洛谷,原作者为

yaoxi
**搬运于
2025-08-24 22:37:34,当前版本为作者最后更新于2022-04-05 15:32:34,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题面
解法
同届的巨佬们已经都通关了 USACO,只有我还在做 Gold 组的蓝题可以发现确定了 的值以后就知道了其他的所有 ,构造方法如下:
$$s_i = \begin{cases} r_i ,& r_i < s_1 \\ s_1 ,& l_i \le s_1 \le r_i \\ l_i ,& s_1 < l_i \\ \end{cases} $$让所有 都尽量靠近 显然使得 最小。
而此时的 也很容易一遍 进行 的计算,但是复杂度 。
思考 对答案的贡献,显然就是 ,可以预处理出 和 的最大值 计算。
但是这不是最终的答案,有可能有 的祖先 使得 (反之同理,即 )。而此时,由于要让所有 靠近 ,则 的取值一定为 , 的取值一定为 ,对答案的贡献就成了 。
而如果 和 在 的同侧,那么 的贡献就一定小于 对答案的贡献,这部分可以不用考虑。于是得出重要结论:非根节点和其非根节点的祖先对答案的贡献是固定的。
因此,不难想到可以一遍 就处理出 ,在枚举 的时候可以 加入贡献。于是复杂度变为 。虽然还是无法通过,但是有了不少的优化空间。
由于一部分答案的贡献是固定的,所以我们只考虑另一部分 。那么显然 是最优的。
于是这题就结束了,时间复杂度 ,为一遍 的复杂度。
AC代码
/** * @file: T3.cpp * @author: yaoxi-std * @url: */ // #pragma GCC optimize ("O2") // #pragma GCC optimize ("Ofast", "inline", "-ffast-math") // #pragma GCC target ("avx,sse2,sse3,sse4,mmx") #include <bits/stdc++.h> using namespace std; #define resetIO(x) \ freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout) #define debug(fmt, ...) \ fprintf(stderr, "[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) template <class _Tp> inline _Tp& read(_Tp& x) { bool sign = false; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) sign |= (ch == '-'); for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + (ch ^ 48); return sign ? (x = -x) : x; } template <class _Tp> inline void write(_Tp x) { if (x < 0) putchar('-'), x = -x; if (x > 9) write(x / 10); putchar((x % 10) ^ 48); } bool m_be; using ll = long long; const int MAXN = 1e5 + 10; const int INF = 0x3f3f3f3f; int n, m, tp, fa[MAXN], lp[MAXN], rp[MAXN], ans[MAXN]; vector<int> g[MAXN]; inline void chkmin(int& x, int y) { (x > y) && (x = y); } inline void chkmax(int& x, int y) { (x < y) && (x = y); } int dfs(int u, int mxl, int mnr) { int ret = max({0, lp[u] - mnr, mxl - rp[u]}); chkmax(mxl, lp[u]), chkmin(mnr, rp[u]); for (auto v : g[u]) chkmax(ret, dfs(v, mxl, mnr)); return ret; } bool m_ed; signed main() { // debug("Mem %.5lfMB.", fabs(&m_ed - &m_be) / 1048576); int cas; read(cas), read(tp); while (cas--) { read(n), m = 0; for (int i = 1; i <= n; ++i) g[i].clear(); for (int i = 2; i <= n; ++i) read(fa[i]), g[fa[i]].push_back(i); for (int i = 1; i <= n; ++i) read(lp[i]), read(rp[i]); int mxl = 0, mnr = INF; for (int i = 1; i <= n; ++i) chkmax(mxl, lp[i]), chkmin(mnr, rp[i]); int mn = dfs(1, 0, INF), ansp = 0, answ = INF; for (int i = (mxl + mnr) / 2; i <= (mxl + mnr + 1) / 2; ++i) { int curw = mn; if (i < mxl) chkmax(curw, mxl - i); if (i > mnr) chkmax(curw, i - mnr); if (curw < answ) answ = curw, ansp = i; } write(answ), putchar('\n'); if (tp) { for (int i = 1; i <= n; ++i) { if (lp[i] <= ansp && ansp <= rp[i]) ans[i] = ansp; else if (ansp < lp[i]) ans[i] = lp[i]; else if (rp[i] < ansp) ans[i] = rp[i]; write(ans[i]), putchar(" \n"[i == n]); } } } return 0; }
- 1
信息
- ID
- 7614
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者