CSP-S 2024 第八次

忘记写了,补一下

A

依次加入每个 \(a_i\),拿个大根堆维护当前以 \(i\) 结尾的和最大子段,和超过 \(s\) 了就弹堆顶直到和不超过 \(s\)

……但是这样是错的,考虑加入一个负的 \(a_i\) 后,取堆中最小的几个数使得它们的和大于 \(0\)

则删掉这些数中的最大值后剩下的数也不会被取,也就是说要删掉这些数只需要删一次,把它们拿出来加在一起塞回去即可。

\(s\) 是负数的话删掉所有大于等于 \(s\)\(a_i\) 即可。不过好像出现了一些语文事故,先不管了。

B

倍增预处理出 \(f_i\) 表示 \(i\) 上方第一个大于 \(a_i\) 的点,

询问 \(u,v,c\) 时,先倍增找到 \(u\) 上方第一个大于 \(c\) 的点 \(x\),然后就要求跳(\(x\gets f_x\))几次能跳出 \(v\),在 \(f\) 上倍增即可。

C

最大值最小,先二分最大值 \(K\)

\(f_{u,x,y}\) 表示是否存在走完 \(u\) 子树,\(u\) 到第一个叶子的距离为 \(x\),最后一个叶子到 \(u\) 的距离为 \(y\) 的方案,

可以发现 \(x\le x',y\le y',f_{u,x,y}=1\) 时我们就不关心 \(f_{u,x',y'}\) 了,所以在我们关心的状态中 \(y\)\(x\) 的增大而减小,

而且我们关心的 \(f_{u,x,y}\) 只有 \(O(s_u)\) 个(\(s_u\)\(u\) 的叶子个数),因为 \(x,y\) 都只有这么多种。

考虑转移,钦定先走左子树时,对于左子树 \(l\) 中每个我们关心的状态 \(f_{l,x_1,y_1}\)

其能与右子树 \(r\) 中的 \(f_{r,x_2,y_2}\) 合并成 \(f_{u,x_1,y_2}\) 当且仅当 \(y_1+v_l+v_r+x_2\le K\)

\(y_2\) 肯定越小越好,所以肯定取满足条件的最大的 \(x_2\) 进行转移,双指针维护。

钦定先走右子树同理,最后只留下我们关心的状态就行。

D

【模板】最小斯坦纳树

\(f_{u,S}\) 表示以 \(u\) 为根的树覆盖 \(S\) 中的点的最小代价,考虑转移:

  • 不改变根,可以合并已有的两棵树,即 \(f_{u,S}+f_{u,T}\to f_{u,S\cup T}\)
  • 改变根,可以在根上连接一条边,即 \(f_{u,S}+e(u,v)\to f_{v,S}\),其中 \(e(u,v)\)\(u,v\) 之间的边权。

第一种转移直接枚举子集做,第二种转移类似 Dijkstra 地做即可。

posted @ 2024-10-03 18:08  5k_sync_closer  阅读(55)  评论(11编辑  收藏  举报