Codeforces Round 967 (Div. 2)
题不难。
A. Make All Equal
题意: 一个圆,上面有 \(n\) 个数,每次可以删去相邻的两个不同数中任意一个,求至少几次使得剩下的数都一样。
显然下界是出现次数最多的数且一定能取到,时间复杂度 \(O(n)\)。
B. Generate Permutation
题意: 要求构造一个排列,使得 \(x\) 所在位置大于 \(x+1\) 的与 \(x\) 所在位置小于 \(x+1\) 的个数相同。
考虑到关系总共 \(\frac{n-1}{2}\),显然 \(n\) 为偶数无解,\(n\) 为奇数时可以 \(n, n - 2, n - 4, \dots, 1, 2, 4, \dots, n - 1\) 构造。
C. Guess The Tree
题意: 交互题,有一棵树,每次可以询问两个点的路径的中点(如果偶数就输出靠经第一个的点),要求在 \(15n\) 内构造这棵树。\(n \le 1000\)。
这个限制显然是大概 \(O(n \log n)\) 级别的。我们发现,如果对于 \(a,b\) 有 \(f(a,b) = a\) 则说明 \(a\) 到 \(b\) 右边。
我们选 1 号点为根,这样我们可以求出所有与 \(1\) 号点距离为 \(1\) 的点。
如果我们对于一个点对颠倒顺序询问两次就能得到这条路径是否为偶数,所以我们可以依次发现距离为 \(2,3,\dots\) 的点,每次只用不断查询中点即可。
这个题 \(O(n^2)\) 可过,用 bfs 优化一下应该就能做到 \(O(n \log n)\) 了。
D. Longest Max Min Subsequence
题意: 选取一个序列的最长子序列,要求所有数互不相同,且将所有奇数位取反后的字典序最小。\(n,a_i \le 3 \times 10^5\)。
显然最长长度是确定的,我们按位确定。
我们记录 \(last_i\) 表示 \(i\) 这个数最后出现的位置,显然选取第一个数必须在 \([1, \min_i\{last_i\}]\) 之间。
则我们贪心地选取这些数中最大的那个,然后就是后面的事儿了。
整个过程可以用一个 set 维护所有的 \(last_i\),当一个数被选中时就将其 \(last_i\) 删去。
我们还要维护一个右边界 \(L\),表示上一个数位置是 \(L\),后面的数都要在这之后。同时对于前面的数维护两个 multiset,第一关键字是值,第二个是位置,但是其中一个的位置要取反。
每次我们选一个最大最小时,如果有多个就选最前面的。所以需要两个 multiset。
然后就没了,记得要把不合法地弹出。
E1. Deterministic Heap (Easy Version)
题意: 对于一个满二叉树的大根堆,我们定义其可以唯一确定当且仅当进行一次 pop 操作时,不会出现两个儿子权值相同的情况。初始有一个高为 \(n\) 的满二叉树都是 \(0\),你可以恰好执行 \(m\) 次操作,每次将一个点到根路径上所有数加一,求最后有多少不同的可以唯一确定的大根堆。\(n,m \le 500\)
显然 dp 题。
我们观察到根的权值一定是 \(m\),所以我们可以 dp,设 \(g(i,j)\) 表示高为 \(i\),恰好执行了 \(j\) 次操作的方案数。
我们发现只需要枚举儿子谁更大即可,为了使得儿子方便枚举,我们要求上面的状态还要满足没有执行 \(i\) 自己加一的操作,同时定义
\(h(i,j)\) 表示高为 \(i\),恰好执行 \(j\) 次大根堆个数(其实也可以直接挡板法计算)。
不妨设 \(g'\) 是 \(g\) 对于 \(j\) 的前缀和,我们得到:
然后就可以在 \(O(nk^2)\) 内解决了。
E2. Deterministic Heap (Hard Version)
题意: 现在定义唯一确定指执行两次 pop 都不会出现两个儿子权值相同的情况。求方案数。\(n \le 100, m \le 500\)。
其实不难。
我们发现由于需要两次 pop 所以我们需要记录儿子中的最大值。不妨设 \(f(i,j,k)\) 表示高为 \(i\),执行了 \(j\) 次(自己没有),儿子最大的为 \(k\) 的方案数。
相应的,我们设 \(g(i,j,k)\) 同上题,其中 \(k\) 记录儿子最大值,\(h(i,j)\) 不变。
我们讨论两种情况:
第一种,如果两次 pop 都去了同一颗子树,则:
第二种,如果两次 pop 去了不同子树,则:
前缀和优化一下就行了。注意每次 pop 会赋值为 -1,所以值域要加 1。