三个题
CF1870G
考虑如何 check 答案是否大于等于 \(k(k \ge 1)\)(假设现有的元素个数大于 \(1\)):
考虑最后一次合并:我们需要得到 \(0,1,2,...,k-1\)。
考虑找到最大的没有出现过的数 \(s\),那么我们要得到 \(s\) 又至少需要 \(0,1,2,...,s-1\)。后面可能还有一些不够的数,那就需要更多的数来填充。
所以考虑按照值 \(p\) 从大往小做,维护一个 \(need\) 表示我们需要 \(need\) 个 \([0,p-1]\)。
设 \(cnt_p\) 为 \(p\) 出现的次数。
- 如果 \(cnt_p < need\),那么剩下的数我们额外需要 \(need-cnt_p\) 个。
- 如果 \(cnt_p \ge need\),那么多余的那些数,我们可以对使用 \(\operatorname{mex}(p) = 0\) 把它们变成 \(0\),这样就可以 \(cnt_0 \texttt{ += } need-cnt_p\) 了。
最后再看看 \(cnt_0\) 和 \(need\) 的大小关系即可。
注意到在位置 \(p\) 遇到第一种情况时,我们的需要的元素个数增加了 \(p-1\)。因此如果是可行的,需求的元素个数总和不会超过 \(n\),执行第一种情况的的位置的编号和必然也是 \(O(n)\) 的。这些编号是互不相同的,所以只会遇到 \(O(\sqrt{n})\) 次第一种情况。
在序列上从左往右做,注意到答案是递增的且不会超过 \(n\),所以只需要 \(\Theta(n)\) 次 check。在线段树上面找满足第一种条件的 \(p\),可以证明是 \(\Theta(n \sqrt n)\) 的。
考虑如何更优。
先看看如何快速维护最后的 \(need\):每个位置是一个关于 \(need\) 的一次分段函数,在 \(need \le cnt_p\) 时斜率是 \(1\),\(need > cnt_p\) 时斜率是 \(2\)。
因此一段区间 \([L,R]\) 也是一个分段函数。
现在我们在线段树上面暴力维护这个分段函数,并把值超过 \(n\) 的部分砍掉。接下来证明一个节点最多只会有 \(\Theta(\log n)\) 段:
考虑更暴力的得到分段函数的方法。就是从 \(R\) 开始,依次把 \(f(x)\) 变成 \(\max(f(x),2f(x)-cnt_p)\)。
设 \(t\) 满足 \(f(t-1) \le cnt < f(t)\)。观察 \(f(x)-f(x-1)\) 的值,它在 \(x< t\) 的位置不变,在 \(x=t\) 的位置增加了一个值,在 \(x>t\) 的位置乘了 \(2\)。
那么在刨掉 \(>n\) 的部分后,最后一个位置被乘 \(2\) 的次数必然不会超过 \(O(\log n)\),因此只有 \(O(\log n)\) 次有效的操作,所以分段函数的段数也是 \(O(\log n)\)。
维护 \(cnt_0\) 也可以用类似的方法。
时间复杂度 \(\Theta(n \log^2 n)\)。如果是修改是增加 \(t\) 个 \(a_i\) 这个算法就相当有优势了。
QOJ6794
观察到,执行了一次区间加后,不会有与之相交的区间减操作。证明就是考虑如果有,那么就找到和他相交的第一个,刨掉相交的那一部分一定不劣。
因此题目就可以看成先进行一堆区间减操作,再进行一堆区间加操作,问最小操作次数。
这是一个线性规划问题,猜测整数最优解也是实数最优解。对偶之后 dp 即可。
时间复杂度 \(\Theta(n)\)。
SNOI2022 倍增
本来想加强一下放 noip 模拟赛的,后来发现 loj 上已经有这种做法了,十分遗憾。
首先这题等价于对于 \(B\) 找到最小的满足条件的 \(n\)。因为可以在最优解里面插一堆 \(B-1\)。
这个 \(n\) 不会很大,因此一个比较暴力的想法是暴力枚举对应关系的排列,暴力枚举进位。
考虑把排列的环抠出来。不妨是 \(p_1 \to p_2 \to ... \to p_k \to (p_{k+1}=p_1)\)。(这里的 \(p\) 表示排列对应位置上的值)。
不妨 \(c_i\) 是第 \(p_i\) 位得到的进位数量,那么 \(2p_i+c_i \equiv p_{i+1} \pmod B\)。
所以就有 \(2^k p_1 + \sum_{j=1}^{k} 2^{k-j} c_j \equiv p_1 \pmod B\)。
设 \(C = \sum_{j=1}^{k} 2^{k-j} c_j\),显然 \(0 \le C < 2^k\)。
不妨设 \((2^k-1)p_1 + C = tB\),可以发现 \(0 \le t \le 2^k\)。
而有了 \(t\) 之后,由于 \(C \le 2^{k}-1\),所以 \((p_1,C)\) 只有 \(\Theta(1)\) 种方案。
然后我们就可以算出来每个位置被前面的那个位置进了多少位,向后面的那个位置进了多少位。
而最后的那个数就是 一条在 \(0,1\) 两个点的图上的欧拉回路。这就要求了 \(0 \to 1\) 和 \(1 \to 0\) 的边数相同。
我们抠出来的环的 \(0 \to 1\) 和 \(1 \to 0\) 的边数不一定相同,所以要选多个环。这个可以背包解决。
设 \(k\) 是答案,时间复杂度 \(\Theta(k2^k)\)。aclink。