2023 杭电多校 Day1
1009
签到, 队友哥切的, 没看
1002
\(f(x, 0/1/2)\) 表示当前点没有覆盖/覆盖/放置观察点 子树内最小代价, 简单转移即可。
f[x][1] = 1e18;
f[x][2] = a[x]; f[x][0] = 0;
for (int y : e[x]) if (y != fx) {
dfs(y, x);
static i64 g[3];
g[0] = g[1] = g[2] = 1e18;
g[1] = f[x][0] + f[y][2];
g[1] = std :: min( {g[1], f[x][1] + f[y][2], f[x][1] + f[y][1] } );
g[2] = std :: min( {g[2], f[x][2] + f[y][0], f[x][2] + f[y][1], f[x][2] + f[y][2]} );
g[0] = std :: min( {g[0], f[x][0] + f[y][1]} );
g[1] = std :: min( {g[1], f[x][0] + f[y][2]} );
f[x][0] = g[0];
f[x][1] = g[1];
f[x][2] = g[2];
}
1010
这个一看就是 \(x\) 递增条件比较关键, 可以观察到当 \(a_i\) 第一次比 \(x\) 小以后, 以后的操作都是取反然后加上 \(x\) 。
我的做法就是开一个线段树维护原来的序列, 开一个线段树维护另外一个序列, 每次发现区间有值会第一次比 \(x\) 小就暴力递归下去把这个值删掉, 然后加入另外一个线段树。这样的话每次在两棵线段树上面区间取反, 区间加法。在第一个线段树上发现有要删掉的点就暴力递归, 复杂度一个 \(\log\) 。
1005
最小表示法即可。
比赛的时候骗学长写了个倍长再哈希的做法, 还被卡常数了(
真正的战犯往往没有写这题的代码
1006
\(10\) 组询问一看就是用来暴力的。
一眼 DP, 设 \(f_x\) 表示跳到 \(x\) 的最小代价, 转移就是
经典斜率优化形式, 但是显然我事不会去写启发式合并平衡树维护的凸包的, 也不想去写什么定期重构之类的鬼东西, 点分治斜率优化也行, 但是还是懒得写, 所以选择使用李超树维护。
李超树合并即可。
李超树合并和普通线段树合并基本一致, 只是当两边存在的时候多了一个插入直线的操作, 但是事实上加入操作以后仍然是单 \(\log\) 的。
复杂度不记得怎么证明了, 反正跑得快。
1012
换根维护一下即可。
结论来自于 POJ3710
1003
区间 dp, 赛时没时间写完了。其实是赛时马上就要结束了没注意到等级会小于等于7懒得写了
注意到这个以后直接 \(dp(l, r, x, k)\) 表示 \((l, r)\) 区间,留下 \(x\) 等级 \(k\) 号卡片, 简单转移一下就做完了。
1001
队友哥写的, 可惜 G 了。
暴力枚举相交路径上每一个点计算相遇最短时间, 直接 exgcd 算最小解即可, 代码还没写, 睡觉觉捏