public judge 做题记录

Public Round 1

A 删数

这个太奇怪了啊!!!

一步显然的转换:求出原序列的差分数组,相当于每次把相邻两项相同的数合并成他们的和,要删去最多的数。

哪些数有可能被一起删掉:1.正负一定相同;2.去掉二进制的最后的 \(0\),剩下部分相同,实现方式是令 \(x\rightarrow\frac{x}{\operatorname{lowbit(x)}}\)

我们把满足以上条件的极长的连续段拎出来对它计数。可以 dp,设 \(g_{i,j}\) 为右端点为 \(i\),合并出 \(2^j\) 倍的左端点,若不存在为 0,这部分可以简单递推。

\(f_i\)\(i\) 为右端点合并他所在的连续段的答案。那么:

\(f_i=\min\limits_{j\in[0,\log v]}(f_{g_{i,j}-1}+1)\)

总复杂度 \(O(n\log v)\)代码实现

B 守卫

这个太精妙了啊!!!

首先所有边一定属于原图的最小生成森林,这部分显然,调整证明即可。

联通相关,考虑 kruskal 重构树(森林),转换题目的限制:守卫向叶子节点。若属于同一连通块的两叶子同时被选中,需要断开两点路径上的一条边;每一个连通块的根必须可达一个守卫。

这个东西很网络流啊!考虑设计这样的费用流模型:

1.源点向每个守卫连边,流量为 \(1\),费用为 \(0\)

2.守卫向每一个他能到的叶子节点连边,流量为 \(1\),费用为 \(0\)

3.重构树上除根的每一个点向他的父亲连边,流量为 \(1\),费用为 \(0\)

4.重构树上的非叶子节点向汇点连边,流量为 \(1\),费用为流量为 \(1\),费用为它代表的边的权值,意义为可以用这个代价把它割掉。

5.重构树上每一连通块的根向汇点连边,流量为 \(1\),费用为 \(inf\),意义是只有一个守卫能通过根流向汇点,而其他的守卫必须靠割掉某一条边来不与其他守卫联通。

因为根必须有流量,跑最大费用最大流。最后,费用减去连通块数量倍的 \(inf\) 的意义是 割掉一些边使得原图满足条件的边权和的最大值

代码实现

C 直线

谢谢你,计算几何的交互题,连题解都不想看。

ExPR 1

谢谢你,数学题。

A 乘积

为什么就不能对着 dp 式子再多想一会呢?

这个,设 \(f_i\) 为大于等于 \(i\) 的期望步数,有 \(f_i=1+\frac{1}{n}\sum\limits_{j=1}^nf_{\lceil\frac{i}{j}\rceil}\)

\(nf_i=n+f_i+\sum\limits_{j=2}^nf_{\lceil\frac{i}{j}\rceil}\)

\(f_i=\frac{n}{n-1}+\frac{1}{n-1}\sum\limits_{j=2}^nf_{\lceil\frac{i}{j}\rceil}\)

对右边整除分块并记忆化,易于看出来和杜教筛的复杂度一致。代码实现

B 守卫2

这个其实挺好的。

根固定,最优方案一定是选择若干个叶子,显然。

猜了个结论:贪心地选当前价值最大的叶子加进答案,然后这个结论是正确的。

若前 \(i-1\) 次所选都在最优解中,考虑第 \(i\) 次所选的叶子:如果最优解包含当前叶子所在的链,选这个叶子显然最优,否则可调整证明一定不是最优解,即选这个叶子可以让答案变大。于是你可以写点神秘暴力得到一定分。

钦定 \(1\) 为根,设 \(down_x\)\(x\) 子树内距 \(x\) 最远的叶子,\(up_x\) 相对定义为子树外的叶子。对于叶子 \(x\),令 \(a_x\) 为最深的 \(x\) 的祖先 \(v\) 使得 \(down_v\ne x\)。那么如果把 \(x\) 纳入答案,他的贡献是 \(\operatorname{dis}(x,a_x)\)

\(up,down\) 是易于处理的,考虑换根对 \(a\) 的影响,不难发现 \(x\rightarrow v(v\in son_x)\),只会更改 \(up_v,down_v\) 的 权值,于是可以 dfs 的过程中动态维护这些点的权值。需要一个数据结构来支持插入删除,维护前 \(k\) 大的和。

代码实现

C 下降

这个其实挺好的。硬控了我一个下午。

考虑对于一个位置 \(i\) 上的 \(h_i\),若 \([i+1,2n]\) 存在 \(1-h_i\) 所有的数,\(i\) 会被删掉。

于是对于原序列 \(a\),得到操作后的序列 \(b\):从后往前,\(b_i\)\([1,a_i]\) 中最大的不在 \(b_i,b_{i+1}\cdots b_{2n}\) 出现的数,否则为 \(0\)

发现这个就是针对 \(\operatorname{mex}\) 的限制。这启发我们对 \(\operatorname{mex}\) 来计数。

具体地,设 \(f_{i,j}\) 为从 \(2n\) 填数填到 \(i\),当前的 \(\operatorname{mex}\)\(j+1\) 的方案数,答案就是 \(f_{1,n}\)。同时令 \(s_1\) 为当前这个后缀最后存在的个数,\(s_0\) 为最后消失的个数。

特别地,我们先将两个相同的数视作有不同的标号,最后输出的答案应当乘上 \(2^{-n}\)

1.若当前位置最后不存在

相当于限制 \(a_i\le j\),剩下 \(2j-j-s_0\) 个位置供 \(a_i\) 选择,意义是有 \(2j\) 个数,\(j\) 个用来构成 \(\operatorname{mex}\)\(s_0\) 个已经被占。故:

\(f_{i,j}\leftarrow(j-s_0)f_{i+1,j}\)

2.当前位置存在

(1).填的数不改变 \(\operatorname{mex}\)

不对这种转移做特别处理,将他的贡献放到改变 \(\operatorname{mex}\) 时计算:\(f_{i,j}\leftarrow f_{i+1,j}\)

(2).\(\operatorname{mex}\) 有所改变

设之前的 \(\operatorname{mex}\)\(j-k\),则这个位置的贡献是 \(j-k\)\(j-k\) 处有两个空位,\([j-k+1,j]\) 都有一个空位,那么 \(a_i\)\(k+1\) 种取值。

现在要在 \(s_1-(j-k)\) 个未确定的数中选 \(k-1\) 个来凑位数,这 \(k-1\) 个应当最后构成一个 \(j-k+1\)\(j\) 的排列,同时互不相同且大于 \(j-k\)。将这样的方案数作为系数,在这里不妨先记为 \(g_{k-1}\),那么:

\(f_{i,j}\leftarrow\sum\limits_{k=1}^jf_{i+1,j-k}\times(k+1)\times\left(\begin{matrix}s_1-(j-k)\\k-1\end{matrix}\right)\times g_{k-1}\)

这里考虑如何求出 \(g\)。我们不难发现对于 \(g\) 的限制很紧,使得 \(g_{k}\) 恰好等于将序列 \(\{1,1,2,2,\cdots k,k\}\) 变成 \(k\) 阶排列的方案数。

不妨枚举 \(b_1=i\),和 \(f\) 的推导相似:\(a_1\)\(k-i+2\) 种填法,\(<i\)\(>i\) 的部分又各自构成子问题,故:

\(g_k=\sum\limits_{i=1}^k(k-i+2)\times\left(\begin{matrix}k-1\\i-1\end{matrix}\right)\times g_{k-i}\times g_{i-1}\)

\(O(n^3)\) 暴力计算即可。代码实现

PER 1

A 捉迷藏

\(x\) 为根。特判 \(d=1\)\(d=2\)。先找最深的链跳 \(\lfloor\frac{d-1}{2}\rfloor\) 步,此时另一个点是 \(x\) 的一个子结点。

接下来的策略是向上走一步父亲或者向某一个子树走。可以简单维护最大值。然后发现最深的链一定是直径的两个端点,以这两个端点为根就好。代码实现

B 新问题

考虑把序列做一遍单调栈,记录出栈和入栈的操作。就可以还原原序列的偏序关系。查询的时候直接在单调栈上二分即可。代码实现

PR 13

A 旋转序列

我唐完了啊,不会简单构造。

答案下界是 \(\lceil\frac{k\times l}{n}\rceil\)。在 \(A\) 串撒连续的 \(k\) 个点。把 \(B\) 串视作环每 \(k\) 个撒一个点即可。代码实现

posted @ 2024-07-24 21:31  xlpg0713  阅读(34)  评论(0编辑  收藏  举报