[NOI 2020] 命运

一些闲话:完了完了好废啊,这题都没做过是不是药丸。根本没有想到子树 \(\tt dp\),没有注意到每条路径都是 "祖先 \(\to\) 子孙" 这个形式的提示欸……

\(dp(u,i)\) 为已经考虑子树 \(u\) 内边的赋值情况,目前 未满足 且下端点属于子树 \(u\),上端点深度最大值为 \(i\)(特别地,如果全满足则为零)的子树内边赋值方案数。对于父子关系 \(u\to v\) 有这样的转移

\[dp(u,i)\gets \sum_{j=0}^{d_u}dp(u,i)dp(v,j)+\sum_{j=0}^i dp(u,i)dp(v,j)+\sum_{j=0}^{i-1}dp(u,j)dp(v,i) \]

转移基于边 \((u,v)\) 的赋值情况分类讨论。第一个和式是赋值为 \(1\) 的情况,此时对于 \(j\leqslant d_u\)\(dp(v,j)\) 一定都满足了之前未满足的限制,而且由于 \(i<d_u\)(否则不可能合法),所以剩余的 \(dp(v,j)\) 也没有贡献了;后面两个和式就是赋值为零的情况。

为了加速运算不妨设 \(\displaystyle f(u,i)=\sum_{j=0}^i dp(u,j)\),那么有

\[dp(u,i)\gets dp(u,i)\cdot (f(v,d_u)+f(v,i))+dp(v,i)\cdot f(u,i-1) \]

这个柿子可以线段树合并,\(f(v,d_u)\) 在合并外计算即可。这么讲你肯定是听不懂的,但是看代码一定能懂:\(\scr Submission\).

[CEOI 2019] Magic Tree

一些闲话:突然感觉这种闲话格式也挺好的,就像不经意拾起一些生活的碎屑,然后微微惊讶 —— 原来我的闲话里全是 好困不文明用语 以及 😅😢🥲😵‍💫😭🥺。那么我今天要说的话就比较典型了 —— md 又感冒了,真的好困啊 🥺🥺🥺。非常烦躁的是教练拿给我一套题做,然后啥也不会直接睡觉,下午来才发现 \(\mathcal T_1\) 自己做过。

首先肯定做子树上的 \(\tt dp\),设 \(dp(u,i)\) 为子树 \(u\) 在时间 \(i\) 之前被断开能得到的最大果汁,转移有:

  • 不获取 \(u\) 点的果汁:\(dp(u,i)\gets \sum dp(v,i)\)
  • 获取 \(u\) 点的果汁:\(dp(u,t)\gets w_u+\sum dp(v,d_u)\),其中 \(d_u\leqslant t\).

这两种操作需要取 \(\max\),可以考虑线段树合并,合并方式实际上和上文的 [NOI 2022] 命运 一题是一模一样的,用二元组 \((v,\text{tag})\) 维护(注意此时 \(v\) 代表的不是 "时间 \(i\) 之前" 而是 "时间 \(i\)")。时间复杂度 \(\mathcal O(n\log n)\).

再记录一种方法。还是利用 \(\tt dp\) 值不降的性质,我们可以用 map/set 维护 \(\tt dp\) 值的拐点,当然,为了将区间转化成拐点,需要对 \(\tt dp\) 值进行差分。显然每个点至多增加一个拐点,再加上启发式合并就是 \(\mathcal O(n\log n\log k)\) 的。代码量非常小清新。

UOJ - 346 某位歌姬的故事

一些闲话:要中暑了。不想说话。

首先将序列按询问划分成若干个区间,用序列 \(\{a\}\) 表示(其中第 \(i\) 个区间就是 \([a_i,a_{i+1})\))。设 \(\text{up}_i\) 为第 \(i\) 个区间能取得的最大值,只要用所有覆盖此区间的询问 \((l_i,r_i,m_i)\)\(m_i\)\(\min\) 即可。

一个非常重要的 observation 是只有 \(\text{up}_i=m_j\) 的区间才可能满足询问 \(j\) 的最大值条件。考虑若 \(\text{up}_i<m_j\),那么 \(m_j\) 根本取不到;若 \(\text{up}_i>m_j\),那么询问 \(j\) 压根没覆盖这个区间。

于是各个最大值之间都是独立的。枚举最大值 \(v\),选出所有 \(\text{up}_i=v\) 的区间和 \(m_j=v\) 的询问进行 \(\tt dp\),问题就转化成有多少种给区间赋值的方法,使得每个询问都至少包含一个值为 \(v\) 的元素。记 \(dp(i,j)\) 为前 \(i\) 个区间,最后一个取 \(v\) 的元素在区间 \(j\) 的答案。转移有

\[dp(i,j)= \begin{cases}dp(i-1,j)\cdot (v-1)^{L_i}, & \text{if } i\ne j\and p_i\leqslant j<i\\\displaystyle \sum_{k=0}^{i-1}dp(i-1,k)\cdot (v^{L_i}-(v-1)^{L_i}), &\text{if }i=j\end{cases} \]

其中 \(L_i\) 是区间 \(i\) 的长度,\(p_i\) 表示如果区间 \(i\) 没有取到 \(v\) 的元素,往左最多可以等到在 \(p_i\) 中取一个 \(v\)。复杂度 \(\mathcal O(Tq^2)\),精细实现可以做到 \(\mathcal O(Tq\log q)\)\(\tt dp\) 时处理原数组的前缀和即可。

随机 / random

题意简述:唐芯刚学会 st 表。唐芯想用 st 表去维护一个长为 \(n\) 且值域为 \([1, V ]\) 的正整数序列 \(a\) 的区间最小值和最大值。但她突然发现有 \(m\) 次修改,每次修改会给出两个整数 \(x, v\),然后将 \(a_x\) 赋值为 \(v\)

唐芯并不会用 st 表支持修改,所以她只好退而求其次,如果能维护出每次修改后,st 表上每个区间的极差的平方和,那么就算完成任务。换句话说,记

\[f(l, r) = (\max\{a_l , a_{l+1}, \dots , a_r\} − \min\{a_l , a_{l+1}, \dots , a_r\})^2 \]

你需要在每次修改后求出

\[\sum^n_{l=1} \sum^n_{r=l} [r − l + 1 = 2^k ]f(l, r) \]

为了体现题目名称,数据保证 \(a_i , v\)\([1, V ]\) 中独立均匀随机,\(x\)\([1, n]\) 中独立均匀随机。

\(1\leqslant n,m\leqslant 5\cdot 10^5,1\leqslant V\leqslant 2\cdot 10^5\).

差点没有成功签到。事实上这题直接暴力递归 st 表进行修改,当递归当 \(\max,\min\) 均未改变时停止即可。原因是在随机数据下,每个值作为区间 \([l,r]\)\(\max/\min\) 的概率为 \(1/(r-l+1)\).

生成树 / tree

题意简述:平面上有 \(n\) 个点,两个点之间的距离定义为曼哈顿距离,求这 \(n\) 个点的最大生成树。

\(n\leqslant 2\cdot 10^6\).

一些闲话:不会 \(\rm prim\) 见祖宗。

考虑 \(\rm prim\),可以发现,只要快速算出当前树与未连接点的距离最大值就可以通过此题。一个非常经典的转化是(喂你这个人事后诸葛亮有什么用啊!)点 \(a,b\) 之间的曼哈顿距离是四种给 \(x_a,x_b,y_a,y_b\) 赋正负号的方案中,带权和最大的方案,这和我们求最大值的目标不谋而合。于是用堆来维护 \(x+y,-x-y,x-y,y-x\) 四种情况即可。复杂度 \(\mathcal O(n\log n)\).

另一种方法仍然基于 \(\rm prim\),只不过将曼哈顿距离转化成切比雪夫距离,它同样也是用 \(\max\) 计算的。然后我们可以贪心地求解 —— 先选出切比雪夫距离最大的一对点 \(a,b\)(不妨设贡献到切比雪夫距离的是 \(x\) 坐标),不妨把 \(a\) 置为 \(\rm prim\) 的起点,于是第一条边就会选择 \((a,b)\),将 \(b\) 加入这棵树。

将所有点按 \(x\) 或按 \(y\) 排序的结果拍成两个序列。如果在按 \(x\) 排序的序列中选边,显然只有可能是 \(x_i\)\(x_a,x_b\) 的最大值,边数为 \(\mathcal O(n)\)(否则不符合 \(\rm prim\));如果在按 \(y\) 排序的序列中选边,同样也只可能是 \(y_i\)\(y_{a'},y_{b'}\) 的最大值(\(a',b'\) 意义同 \(a,b\)),因为从 \(i\) 出发的最大边的另一个端点只可能是 \(a'\)\(b'\),接着再选 \(y\) 就必选 \((a',b')\),然后就又变成了上面的问题。复杂度也是 \(\mathcal O(n\log n)\) 的,但是常数明显优秀一些。

posted on 2021-01-06 22:32  Oxide  阅读(113)  评论(0编辑  收藏  举报