Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final Round) A~F 题解

比赛链接

A

不难发现可以把最大值和次大值翻到一起,输出它们的和即可。

B

一个一个删字符肯定最优,所以最终字符串的起始位置就是 所有出现过的字符中 最后出现位置最靠前 的位置。

C

首先可以知道一开始蛋糕的重量。

然后模拟这个过程,如果当前分出来的最大的一块不可能在最终答案中就一定要分成两半。

代码大概长这样:https://pastebin.ubuntu.com/p/bZNzxzqPBP/

D

因为可以唯一确定信息,所以这些比例关系一定构成了一棵树。

把根节点的信息看成 \(\frac{1}{1}\),根据每条边可以递推得出每个点的信息(注意要约分),然后算出最小的可能分母,进而求得每个点的权值。

实现的时候只需要记录每个点的分子 / 分母和它父亲的差值,在第二遍 dfs 求答案的时候再算出来。

由于数可能很大,所以需要用唯一分解定理的形式存下来。

Code:https://pastebin.ubuntu.com/p/2SxpMYqzkg/

E

发现值域和数字个数只有 \(10^5\),时限又有 5s,一切都指向这是一道根号复杂度的题。

把修改最少的数字转化成保留最多的数字,设公差为 \(d\),那么两个数 \(i\)\(j\) 能够同时保留当且仅当 \(\frac{a_i-a_j}{d}=i-j\),化简可得 \(a_i-id=a_j-jd\)

\(mx=\max a_i\),枚举公差 \(d\),按照 \(d\) 的大小分类讨论:

  • \(|d|\le \sqrt{mx}\),那么可以把 \(a_i-id\) 用一个哈希表存下来,只需要找到哈希表中出现次数最多的数即可。
  • \(|d|>\sqrt{mx}\),因为值域 \(\le10^5\),所以对于一个数 \(i\),只可能保留 \([i-\frac{mx}{d},i+\frac{mx}{d}]\) 内的数(因为如果要保留,这个范围之外的数肯定不在值域范围内了),于是暴力枚举,看要保留哪些数。于是从前往后 DP 即可。

Code:https://pastebin.ubuntu.com/p/2BD3jPc6vv/

F

我们考虑按位从小到大确定答案。

类似后缀数组的倍增构建,设 \(f(s,x)\) 为异或值为 \(x\) 时对 \(s\) 变换后的得到的字符串,\(p_k\) 是一个长度为 \(2^n\) 的数组,它的第 \(i\) 位是在只考虑前 \(2^k\) 位时 \(f(s,0),f(s,1),\dots,f(s,2^n-1)\) 中第 \(i\) 小的 \(x\)

\(p_{k-1}\) 递推到 \(p_k\) 只需要做一遍排序即可。不得不说这个 idea 是真的巧妙。

Code:https://pastebin.ubuntu.com/p/QgCBfNSWFN/

posted @ 2022-03-22 08:55  csxsi  阅读(108)  评论(0编辑  收藏  举报