Codeforces Round 1094 Div.1 做题记录
Codeforces Round 1094 Div.1
| 编号 | CF2222 |
|---|---|
| 赛时解决 | A,B,C |
| 赛后订题 | A,B,C,D |
Solution
A
容易发现必须含 \(100\),才能分成 \(1\)。
B
容易发现奇数位置和偶数位置是独立分开的,贪心去取即可。
C
我的做法是先用对顶堆做出来每个奇数区间的中位数,这是 \(O(n^2 \log n)\) 的。
然后离散化,令 \(dp[i][j]\) 表示 \(1 \sim i\) 中中位数均为 \(j\) 时的段数,分不了则为 \(-\inf\)。
直接 DP 即可,时间复杂度 \(O(n^2 \log n)\)。
题解中说这些子区间的中位数一定是整个区间的中位数。
证明考虑每个子区间内大于中位数 \(mid\) 以及小于 \(mid\) 的数的数量是相等的(我们可以把部分 \(=mid\) 看成大于或小于 \(mid\))。
因此总共合在一起就是对的了。
所以求出来整个区间的中位数之后,只需要维护大于和小于 \(mid\) 的个数,递推即可。
时间复杂度 \(O(n^2)\)。
D
赛时有思路,但是实现过于复杂(两棵权值线段树),难以解释。
看到逆序对 \((i,j)\) 的贡献为 \(\sum_{k=i}^{j-1} a_k\),很容易想到前缀和的形式,即:
因此考虑令 \(b_i = \sum_{k=1}^{i-1} a_k\)。
那么上式就等价于 \(b_j-b_i\)。
考虑一种理想情况,也就是所有 \(b_j - b_i \ge 0\) 的逆序对 \((i,j)\) 都被选上了。
记 \(i\) 最后的排名为 \(p_i\),那么我们希望:
- 对于 \(i<j\) 且 \(b_j \ge b_i\),都有 \(p_i < p_j\)。
- 对于 \(i < j\) 且 \(b_j < b_i\),都有 \(p_i > p_j\)。
我们发现,\(b,p\) 之间存在相反的关系。我们不妨根据这一点考虑构造:令 \(i\) 按照 \(b_i\) 降序排序,此时 \(i\) 所在的位置即为 \(p_i\)。
时间复杂度只有排序的 \(O(n \log n)\)。
E
感觉比 D 还简单?赛后独立切了!
简单想一下 \(\text{and,or,xor}\) 的性质,不难想到一种构造方式。见下表。
| 运算符号 \ \(f(x)\) \ \(x\) | \(0\) | \(2^n-1\) |
|---|---|---|
| \(k = 1 \ \ (\text{and})\) | \(0\) | \(c\) |
| \(k=2 \ \\ (\text{or})\) | \(c\) | \(2^n-1\) |
| \(k = 3 \ \ (\text{xor})\) | \(c\) | \(c'\)* |
*:其中 \(c' \oplus c = 2^n-1\),\(c \ \& \ c' = 0\),\(c\ |\ c' = 2^n-1\)。
看 \(x = 0\) 的这列,发现 \(f(0)\) 的结果只有 \(0\) 或 \(c\)。
这是比较好判断的。我们不妨考虑让 \(0\) 作为集合中的初始元素,然后第一次把 \(f(0)\) 放进去,得到一个返回的集合大小。
显然集合大小 \(=1\) 时 \(k = 1\),否则 \(k = 2/3\)。
接下来就可以分讨了。
- 若 \(k = 1\):
- 将 \(f(2^n-1) = c\) 加入集合中,并二分查找出 \(c\) 即可。
- 若 \(k = 2/3\):
- 此时 \(c\) 就在集合中,直接二分出 \(c\)。
- 接下来需要判断 \(k\) 的值,目前集合中只有 \(\{0,c\}\)。
- 考虑放入一个 \(f(p)\),使得 \(k=2/3\) 时 \(f(p)\) 的值一定不同。
- 这里我们构造 \(p = 2^w\),其中 \(2^w < c < 2^{w+1}\)。此时若 \(k = 2\) 则集合大小不变。
- 不过考虑 \(2^w = c\) 的情况,不是很好处理,那干脆直接把 \(f(2^n-1)\) 加入集合(因为本题中 \(n \ge 2\),不会出现 \(2^n-1 = 2^w\))。然后询问集合中 \(\ge 2^n-1\) 的数的个数,如果为 \(1\) 则说明 \(k = 2\),反之 \(k = 3\)。
询问次数至多 \(n+3\),复杂度 \(O(Tn)\)。

浙公网安备 33010602011771号