record 6.17-6.18
[abc358 G]
最烂完的一集,搞不懂了。
首先,你发现自己如果走的路径是 \(p\),那么你考虑给它们分配系数,显然你会每个都分配 \(1\) 然后剩下的全都堆到最大值上头去。
进一步,你发现走到最大值之后继续走是没有意义的,进一步,你发现走重复的点是没有意义的。
所以,现在你枚举一个终点,那就变成了起点、终点确定,不能走重复点的路径。然后我在这里想了很久,觉得这路径多得一匹啊,虽然它只有两个参数 \((c,s)\),但是你也不好统计啊。
发现糖丸了。我们记录路径长度 \(c\) 对应的最大的 \(s\) 就行了,这复杂度大概是 \(O(n^4)\),可以通过。
[CF1978 C]
不知道为啥,别的差不多都会,为啥这东西 8k 人过了我不会啊???
额沿用场上的思路写了一下,然后就过了。。。
看了一眼别人的代码,写得更好一点。他是维护两个指针,然后如果 \(k\) 够就 swap 两个位置,然后指针都移动。否则就移动其中一个指针。
别的题跟我想得一样,就没啥好说的了。
[百度之星 2024 第二轮初赛] F
因为题目还没公布,所以我先把题面记一下防止自己忘了。
给一个数组 \(a\),一次操作是选两个位置,一个 \(+1\) 一个 \(-1\)。你最多操作一次,最大化整个数组的乘积。
\(n\le 10^6,|a_i|\le 10^9\)。
场上想了巨大力分类讨论,要吐了/tuu。
然后又想了一个加点枚举的东西。
你考虑如果有 \(0\),三个以上就没救了,两个那只能是 \(+1,-1\),一个就看这个 \(0\) 需要变成 \(+1\) 还是 \(-1\) 然后随便做做。
考虑没有 \(0\)。比方说我们枚举那个 \(-1\) 的数,考虑所有数的乘积是 \(prod\),你选的数分别是 \(x,y\),那么答案就是 \(prod\frac{(x-1)(y+1)}{xy}\),当 \(x\) 固定的时候,就是 \(prod\frac 1x(x-1+\frac{x-1}y)\),也就是说 \(y\) 应该怎么选就看 \(x-1\) 的符号就行了。总之我们能找到怎么选。
剩下还有一个问题,怎么比较两个方案的优劣。考虑把系数存下来,你可以用浮点数,也可以分别存下来 \(x,y\)。总之都无所谓。
[百度之星 2024 第二轮初赛] G
在一张有向图中,我们称一个点是关键的,当且仅当删除这个点之后,整张图的 scc 个数严格增加。你需要判断每个点是不是关键的。
\(n,m\le 10^6\)。
显然每个 scc 是各自独立的,现在变成了整张图是一个 scc 的问题。
考虑到点 \(u\) 是关键点,当且仅当存在有序点对 \((x,y)\) 满足删去 \(u\) 之后不存在 \(x\to y\) 的路径。
这东西有点支配树的感觉不是吗。上面那个条件相当于在说,以 \(x\) 为根建立支配树,\(u\) 是 \(y\) 的祖先。
换句话说,为了让 \(u\) 不是关键点,以任意其他点为根建支配树,\(u\) 都得是叶子。
但其实没必要这么干。注意到如果在正图和反图支配树上,\(u\) 都是叶子,这就说明删掉 \(u\) 之后存在任意两点之间的路径。并且这条件是充要的。
因此这是个支配树板子题,问题是我不会做任意有向图的支配树。
[百度之星 2024 第二轮初赛] H
你要打核爆,因此你需要依次释放若干个辅助技能,最后释放一个攻击技能。
辅助技能持续 \(a_i\) 秒,并且有 \(b_i\) 秒的技能动画,在动画过程中不能释放其他技能。同一辅助技能可以释放多次,效果叠加。
攻击技能有 \(c\) 秒的技能动画,在动画结束的那一秒,会产生当前生效的辅助技能个数这么多攻击力。
现在有两种操作,一种是增加一个 \((a,b)\) 的辅助技能,一种是询问参数为 \(c\) 的攻击技能最多能产生多少攻击力。
\(n,q,a_i,b_i,c\le 10^5\)。
注意到一个无法被攻击技能吃到的辅助技能是没有意义的,所以我们释放的所有技能都必须持续到攻击技能释放结束。
进行预处理,\(a\) 变成技能动画结束之后还能持续多久。
考虑维护一个 \(lst\) 表示这些技能还能持续的时间,如果你又释放了一个 \((a,b)\) 技能,那么 \(lst\leftarrow\min(lst-b,a)\),我们要求 \(lst\ge c\) 的前提下,释放的辅助技能越多越好。这东西可以 \(dp_{lst}\) 对吧。
额然后你发现,显然是 \(lst\) 越大,\(dp_{lst}\) 越大,然后就是说,这东西往前连一连形成了一棵树,我们就是要在这个树上跳跳跳。
显然修改会改变这个树的形态,我们来分析一下怎么改变的。
首先,考虑存在两个技能 \((a_1,b_1),(a_2,b_2)\),如果 \(a_1<a_2\) 那么必须有 \(b_1<b_2\),否则我们完全可以用 \((a_2,b_2)\) 来替换。因此这东西是一个单调的。
再考虑每个技能到底是在什么时候使用的,经过分析,如果在 \(p\) 处是 \((a_2,b_2)\) 更优,那么在 \(p+1\) 处不可能是 \((a_1,b_1)\) 更好。
考虑反证法,假设 \(p+1\) 处是 \((a_1,b_1)\) 更好,那么根据条件,我们知道
考虑函数 \(f_a(x)=\min(x,a)\),注意到两边同时加了 \(1\) 但是大小关系反转,这说明
也就是
但是 \(a_1<a_2,b_1<b_2\),所以就矛盾了。
那现在我们手头有一个类似于二分栈的东西,因此总的修改次数是 \(O(n)\) 次。
考虑怎样的数据结构能维护这样的修改。在想一些重构一类的东西。看群里一个人说根号分治,好像很对啊。
注意到 \(b_1<b_2\),这说明如果 \(b\ge\sqrt{n}\),在这些段当中,我们跳跃不会超过 \(\sqrt{n}\) 次。而在 \(b<\sqrt{n}\) 的段当中,我们一次跳一整段,跳跃也不会超过 \(\sqrt{n}\) 次。所以暴力跳就是对的了。
[mxr27 A]
好名字。
每次操作可以加一个点的点权,然后还可以查询到根的路径上权值之和,每种操作分别可以进行 \(2n\) 次,让你还原这棵树以及给出根是谁。
有一个乱搞做法:我们对每个点随机赋一个点权 \(w_u\),然后再询问所有点到根的和 \(s_u\),这个时候,对每个点找 \(s_v=s_u-w_u\) 的点 \(v\),因为值域是 \(2^{64}\),在我们粗略认为 \(s\) 也是随机选择的情况下,错误的概率并不高。所以这个做法也许能通过,我写一发。
真的过了。
考虑一个正确做法。
我们先使用 \(n\) 次修改询问,查出每个点的深度。然后对每层深度依次确定它们的父亲是谁。
在确定本层的父亲是谁之前,先修改上一层的权值,使得上一层到根的路径权值之和为它的编号。这样我们查一下之后减 \(1\) 就是答案了。
[mxr27 C]
咋每场都非得来个唐诗 ds???
显然三类修改操作之间是互相独立的,并且它们可以分别贡献给询问,因此我们只需要分别考虑只存在其中一种修改操作的情况就可以了。
又是约数又是倍数的基本上没救了,直接考虑分块吧。
不是我咋操作 1 都不会做啊,我是唐诗。
好了我现在会了一个唐诗根号老哥做法。
先考虑操作 1,我们对序列分块,这样操作就变成了一些单点修改,一些整块修改。单点修改非常好做,考虑整块修改。对原树进行树链剖分,每个点 \(u\) 维护 \(u\to top_u\) 路径上每个块内数的个数,这样就可以更新了。
考虑操作 2,因为 \(\max d(n)\) 大概是个一两百的样子,所以就直接暴力就好了。
考虑操作 3,对于 \(d\ge\sqrt{n}\),直接暴力修改;对于 \(d<\sqrt{n}\),我们维护它们分别被操作了多少次,然后类似于操作 1 每个点仍然维护这些东西就行了。
可能有更好的做法。这个做法核心就是抓住了修改可以独立地贡献给询问。如果没有这个性质的话,恐怕很难做。
? [mxr27 B]
这个题有点神秘的。
可以离线的部分,我们可以使用莫队加一些什么别的东西来做。最后就是一个要支持插入删除一个数到某个集合中,查询一个集合中元素的最小值这么个东西。
我们来分析一下,怎样的 \(u\) 是 \((l,r)\) 的情况下合法的,或者我们考虑固定 \(u\),然后考虑怎样的 \((l,r)\) 是合法的。
我们考虑 \(u\) 的真实排名和虚假排名之差,显然当 \(r\) 右移时,假排名不变,如果遇到比 \(p_u\) 更小的,那么真排名加,否则不变。因此真减假会加或不变。
当 \(l\) 左移的时候,假排名上升,如果遇到比 \(p_u\) 更小的,那么真排名加,否则不变。因此真减假会不变或减。
而这个排列是随的,所以我们猜测满足条件的区间不会很多。
爆了。\(n=1e5\) 时随机大约是 \(8e8\) 级别。
lxl 说静态离线的分块都不优于莫队,我们现在是在线,考虑把莫队改成分块。
我们维护任意两个块囊括的区域内排序后的结果,顺便算出来每个元素真减假还需要多少才能变成 \(0\)。对于一次查询,同一块内暴力,有多个块的话,我们考虑加入两侧散块的影响。
显然,这影响就是会对值域在一定范围内的加一个数,我们的问题变成了根号次查询值域在某个区间内的,真减假是一个数的,下标最小的一个。
这个你可以开线段树来解决。我想想有没有更好的做法。
额我无语了,怎么这么蠢???你根本没办法存下来任意两个块囊括的区域排序之后的结果。
完全不会了。不想看这个题了。
* [WF 2018] 绿宝石之岛
我们考虑把它的这个变化过程表示一下。显然人并不是很重要,我们更看重绿宝石。因此把绿宝石编号成 \(1\sim n+d\)。
每个人可以当成是一个集合,设第 \(i\) 个人多出来了 \(a_i\) 个绿宝石,要求 \(\sum a_i=d\)。一共有 \(n\times(n+1)\dots\times(n+d-1)=\frac{(n+d-1)!}{(n-1)!}\) 种操作方法。
这对应于 \(\frac{d!}{\prod a_i!}\prod a_i!=d!\) 种操作方法,也就是说,每一个选择 \(a_i\) 的方案都是等概率出现的,我们接下来的问题变成了去求最后选择 \(a_i\) 的方案数。
因为我们要的是前 \(r\) 大的人的期望,所以我们希望在 dp 的同时能够某种意义上知道它们的大小关系。
考虑把 \(a_i\) 画成柱子,然后我们用一根线从上到下去扫,设 \(sum_{i,j}\) 表示目前有 \(i\) 个柱子被扫到了,所有数的和是 \(j\) 时,前 \(r\) 大的和是多少。记录 \(cnt_{i,j}\) 为方案数。
* [CF1845 E]
感觉还行,好歹有点思路。
显然,不断进行这样的操作,我们可以得到所有含有 \(1\) 的个数一样的序列。
注意到这里显然有一个奇偶性一类的东西,并且发现一个序列可以通过两次操作变回来,因此我们要求的实质上是进行 \(k,k-2,\dots\) 次操作,可以产生多少种不同的序列。
考虑两个序列之间的最短距离究竟是多少。这是它们 \(1\) 的位置排序之后差的绝对值之和,证明可以采用调整一类的东西。
那么可以设计 \(dp_{i,j,k}\) 表示目前考虑了前 \(i\) 个位置,有 \(j\) 个 \(1\),距离已经是 \(k\) 了。这复杂度显然是 \(O(n^3)\) 的。
现在问题变成了,你手头有一个长为 \(m\) 的递增序列 \(b\),称一个递增序列 \(a\) 是合法的,当且仅当 \(a_i\in[1,n],\sum|a_i-b_i|\le k\),并且二者奇偶性相同。问你合法的 \(a\) 一共有多少个。
有一个想法是,注意到 \(k\) 其实并不是很大,而它事实上最大可以做到 \(O(n^2)\) 左右,所以我们考虑在这上面做一些手脚。类似于 \(>\sqrt{k}\) 的最多只能有 \(\sqrt{k}\) 个,\(\le\sqrt{k}\) 的可能有很多,但是显然有 \(|i-b_j|\le\sqrt{k}\)。
然后经过一些努力发现好像不太行。
看了一眼 sol,前面的部分都是正确的,但是它说这部分跟正解关系并不大,所以让我们开拓一些思维。
开拓不了一点思维。阅读了 sol。
sol 说我们更换贡献的计算方式,把它摊到 \(i\to i+1\) 之间的空隙上,这样的话,如果前面有 \(x\) 个 \(a\) 和 \(y\) 个 \(b\),那么它造成的贡献就是 \(|x-y|\)。
而因为 \(x-y\) 一次最多 \(\pm 1\),所以 \(|x-y|\) 在整个过程当中都不能太大,大概就是 \(\sqrt{k}\) 级别。所以就做完了。
更换了贡献的计算方式之后,原先看不出的性质就显示了出来。这并不是事先能观察出来的,只有你真正更换计算方式之后才能看到结果。
* [CF1740 F]
统计数 \(i\) 出现了 \(c_i\) 次,然后接下来的过程就是像摊煎饼一样,我们把 \(c\) 依次摊上去,最后得到的就是每个集合的元素个数。
你考虑,一个多重集是合法的充要条件。考虑不动啊。
然后看到了 sol,sol 说得有道理,自己看吧。
* [CF1615 F]
咋是个 *2800,感觉不是很做得出来。
我们先考虑给定两个字符串,问你能不能编辑过去。注意到我们的操作有很好的局部性,它只跟一小部分相关。
我们重点观察 \(1\) 的位置。首先因为每次 \(1\) 个数都是 \(\pm 2\),所以 \(1\) 的奇偶性必须相同。
其次,你发现可以使用 \(2\) 次操作把 \(1\) 移动 \(2\) 格,也就是说,我们可以把位置分成奇数位和偶数位,花费 \(2\) 的代价可以交换相邻两项。
这样交换的部分很清楚了,问题是最初的 \(1\) 可能并不够。现在你发现,它加 \(1\) 一定是同时给奇数偶数各加 \(1\) 个,因此有一些要求。
现在你完全会判定能不能编辑过去了,问题是怎么算编辑距离。
最初的 \(1\) 正好够的情况是非常简单的,问题是可能不够或者超了。
我现在分析遇到困难,原因在于我对这个过程了解得仍然很浅。我不知道什么时候两个数会更改,更改应该在什么位置更改,它们是不是要先移动到一起然后才能改,改了之后还会不会继续移动,更改操作需要奇偶联动,以及移动的过程中可能能省下来一些更改。
我们应该按照一个合理的顺序,依次证明,这样后面的证明可以利用之前的结论,就会轻松很多。
我觉得首先要解决的是能不能让更改都发生在移动之前的问题,但是如果两个数就是不在一块,那它们就是要移动到一起才能更改。
阅读了 sol,非常的牛啊。我们把 \(s,t\) 当中的偶数位置给 flip,那么操作就变成了交换相邻两项。啊这个很厉害,但是我咋知道能这么做的???只能凭感觉吗?
那么接下来就是,你可以交换相邻两项,然后问你编辑距离。这个是老熟人了,就是 \(1\) 的位置排序后对应项差的绝对值之和。
仍然把贡献摊到相邻位置上。
设 \(f_{i,j}\) 表示目前考虑过了前 \(i\) 个位置,\(x-y=j\) 的方案之和。最后答案就是 \(f_{n,0}\)。
sol 里头真的把它拆干净了,自己看看吧。

浙公网安备 33010602011771号