[NFLSPC #6] 等差数列
考虑枚举公差 \(d\),如何求得最少题数 \(m\)?
贪心的想,我们希望的等差数列是一条直线,而增加的数最少就相当于让直线最低且任意点不低过原序列。扫一遍序列,动态维护当先最少需要增加的数 \(f\) 和当前末项大小 \(g\),如果下一项 \(a_i<g-d\),那么直接把下一项增加 \(g-d-a_i\) 即可,否则需要把直线上移 \(a_i-(g-d)\)。归纳不难得出这样是最优的。
得到结论,令 \(f(d)=m\),大胆猜想 \(f\) 是单谷函数。
为什么?考虑直线变斜的过程,我们称完全贴合原序列的点为支点,那么不难发现支点是逐渐后移的。又因为斜度的增加,支点前的点贡献一定单调不减,支点后一定单调不增。所以支点前总贡献不降,支点后总共献不增。又因为 \(f(d)\) 就是这两个贡献加起来,所以 \(f(d)\) 是单谷的。
『STA - R3』Aulvwc
首先有一个显然的结论:划分出来的子序列平均数必然是整个序列的平均数。每个划分平均数是相等的,所有划分的平均数的平均数就是全局平均数,所以结论得证。
为了去除数字数量的影响,进行一步转化:将所有数减去平均数 \(avg\)。这样平均数就为 \(0\)。整个序列和为 \(0\),只要有非全集子区间和为 \(0\),就可以把序列分成两个集合使其合法。
经典的,考虑 bitset 维护。
因为要求了不是全集,我们就钦定任意一个数不选,对剩下的数判断。这样是对的,因为至少有两个集合和为 \(0\),而不选的那一个数最多破坏一个集合。
一个 bitset 记录当前可组合出的数,称其为 \(b\);一个 bitset 记录加入一个数后新增可以被表示的数,称其为 \(c\)。强制钦定选新增的数 \(a_i\),所以 \(c\) 根据 \(b\) 左右移 \(a_i\) 位更新,当前可以表示的数为 \(b\) 和 \(c\) 的按位或,只需要判断 \(c\) 是否包含 \(0\) 即可。复杂度 \(O(\frac{n^2\times|a|}{\omega})\)。
邮箱题
先考虑第一问。
假设现在在点 \(u\),那么下一个能走到的新点只能是 \(p_u\)。因为新钥匙只有一把,所以这是显然的。
因为上述结论,走路其实就是在走置换环,能走到的点也是环上连续的。那么拉出每个置换环单独考虑。
套路的,我们可以找任意一个点断环为链,然后把这个链复制一遍。即这个链是 \(now\) 长 \(len\),那么 \(now_i=now_{i+\frac{len}{2}}\)。
视角转化到链上。问题转化为对于每个点 \(u\) 求出它能走到的最远的点 \(ans_u\)。
结论:对于一个起始点 \(u\),如果能走到 \(v\),那么一定能走到 \(ans_v\)。
钥匙和边是固定的,所以之前能走的现在一定能走。
这个结论启发我们倒着处理 \(ans\)。
对于一个起始点 \(u\),暴力往后跳,每次跳到 \(v\) 就直接跳到 \(ans_v\)。这样复杂度是对的,因为对于一个点 \(u\),它现在可以走到 \(u+1\),那么它未来也一定可以走到,也就是说每个相邻的点只会被真正跳过一次,其他时候都会被优化掉。
那么现在问题就转化为满足什么条件下点 \(u\) 能到点 \(u+1\)。
视角来到固定起始点后,定义点 \(u\) 最远向前能走到点 \(a_u\),最近能从点 \(las_u\) 走到点 \(u\)。
结论:点 \(u\) 能走到点 \(u+1\) 当且仅当 \(a_u\le las_{u+1}\)。
因为对于 \(v< u\),\(v\) 一定能走到 \(v+1\),所以结论是显然的。
接下来考虑快速维护这两个数组。
观察到 \(las\) 不会随着起点改变而改变,那么就先扫一遍所有边,求出 \(las\)。
因为相邻点都有连边,所以一个强连通分量必然是由一个区间的所有点组成。而 \(u\) 与 \(a_u\) 必然强连通,所以 \(a_u\) 的值就是 \(u\) 所在强连通分量的最左点。
向后的边贡献 \(las\),向前的边挂在前面的点上,类似扫描线一样不停加边。一个边 \((u,v)\) 会把两点之间所有强连通分量合并,那扫一遍每个点只会被合并一次,时间复杂度正确。
第二问不难发现就是起点所在强连通分量的大小,顺便维护即可。
Swaps
首先套路的把 \(i\) 和 \(a_i\) 连边。注意到连出来的是内向基环树森林,每棵树之间独立,所以我们只需要研究一棵基环树,全部乘起来即可。
先看看这个树是什么东西。一个点 \(i\) 上写着他指向的点 \(a_i\),操作他可以把他和自己的出边交换,然后因为这个两个点已经改变,他们就不能操作了。
有一个结论:对于一个点,他只能被交换一次。因为他被交换一次后,他上面就写着自己了,再交换对序列没有影响。
所以先考虑树的情况。每个点可以选择操作或者不操作,同时每个点的儿子只能有一个点选择操作。而因为操作完一个点后他和他的父亲都不能再操作了,所以我们必须自上而下的执行所有操作,即每个操作对应的最终结果是唯一的。把他写成 DP,其中 \(v\) 为儿子,\(son\) 为儿子个数。
接下来考虑环怎么搞。先看看这个环是什么东西,每个点上写着不同的数,操作他可以把他和他下一个点交换,然后他们就不能操作了。
我们可以把环上每一个点看成一个根,儿子有连向他的树点和环上他前面的一个点。对他进行上面的转移。
不过我们发现环上会有一些奇怪的限制。比如不能所有环上的点都选择操作,因为这样必然会有一个点无法执行自己的操作。
继续对限制进行探讨,发现如果只有一个点选择不操作,最终的局面一定是每个点都写这他上一个点写的数,即他自己。这个时候那个选择不操作的点也不能和树上的点交换。
继续对限制进行探讨,发现如果有两个点以上的点选择不操作,就没有怪事了,因为环被断成两个链,就没有环的性质了。
所以对于一个环上的点:
最终环上的答案,其中 \(son_u\) 表示点 \(u\) 树点儿子个数:
其中 \(rans\) 表示不考虑所有环限制的操作方案数。\(cans\) 表示除环以外所有树的操作方案数。\(dans\) 表示环上只有一个点不选择操作的方案数。因为只有一个点不选择操作要保留一种情况,和所有点都选择操作抵消,所以最终答案就是上述东西。
注意自环要特判。
「JZOI-1」拜神
先跑 SA。
二分长度 \(L\),check 就看有没有 \(\text{lcp}>=L\) 的。
放到 SA 上相当于从大到小扫 height,每次合并两边的块,求 \(L\) 这个版本区间内是否存在两个数在相同块中。
先看后面的问题,我们可以维护每个版本每个位置在序列上是同一个块的后继,存在就变成区间最小值在区间内,这可能可以主席树。
然后就是如何合并两个块,容易想到启发式合并。set 维护每个块中的点,每次合并更新主席树。接着处理询问,就是在主席树上查区间最小值。
[Ynoi2004] rpmtdq
枚举一下做法,发现可以支配对。即我们只需要保留一部分点对就可以回答所有问题。对于每个没有保留的点对 \((U,V)\) 必然存在保留点对 \((u,v)\) 满足 \(U\le u,v \le V\) 且 \(dis(u,v)\le dis(U,V)\)。
再枚举一下做法,发现可以点分治。
定义 \(dis_u\) 表示 \(u\) 到分治中心的距离。对于两个点 \(u,v\),若存在一个点 \(v<w<u\) 满足 \(dis_v,dis_w\le dis_u\),那么 \(dis_v+dis_w\le dis_v+dis_u\),即 \((v,u)\) 被 \((v,w)\) 支配。类似的,若存在一个点 \(v>w>u\) 满足 \(dis_v,dis_w\le dis_u\),那么 \(dis_v+dis_w\le dis_v+dis_u\),即 \((v,u)\) 被 \((v,w)\) 支配。
于是查前驱后继可以简单求出。随便扫描线即可。
[湖北省选模拟 2024] 永恒 / eternity
怎么判断是否有解?
如果一个连通块黑白染色后同色块有不同的数,那么必然有解。
证明:满足条件则必然存在三个位置 \(a,b,c\) 满足 \(a\neq c\) 且 \(ab,bc\) 相邻。那么我们可以走出:\(a/c,b,a/c,b\cdots\) 的数字。我们全选 \(a\) 后,可以把一个 \(a\) 改成 \(c\),结果会变化 \((c-a)\times 100^k\)。而 \(100^k≡1\pmod {1145141},(c-a)\neq 0\),所以可以取遍所有值。
其他情况路径是确定奇偶性的,暴力情况数 \(1145141\times 10\times 10\times 2\) 线分治维护即可。
[NOI2022] 冒泡排序
干掉矛盾是容易的。
首先答案序列可以调整为 \(a_i\in V\)。
性质 A:限制形如某些区间全为 \(1\),有些区间必须有 \(0\)。那么 \(0\) 肯定贪心的往前选。
性质 B:单点赋值的限制,可以扫描线+线段树+DP。
性质 C:最小值放前面不劣,多了一点大于某一数的限制。还是可以扫描线+线段树+DP。
那么考虑把原题一堆限制改为一些 \(=v\) 一些 \(\ge v\) 的限制。
两个相交的区间若 \(V\neq V\) 则可以缩小一个区间。那么现在相交的全部 \(V=V\),包含的是单调递增的。每个区间第一个数放 \(=V\) 条件,其他位置放 \(>V\) 条件即可。
之后树状数组线段树简单维护。