$Div.2$
A Broken Keyboard
若某段连续出现这个字符 $c$ 的次数为奇数,则字符 $c$ 一定没有坏掉.
时间复杂度 $O(n)$ .
1 | //%std |
B Binary Palindromes
由于对交换的次数不作限制,那么任意一个 $0,1$ 个数都不变的方案,都可以得到.
于是答案只与 $0,1$ 的个数,以及每个串的长度有关.
统计出 $0,1$ 的个数后,对于每个长度确定的字符串,依次构造.
这里可以贪心来放,若串长为偶,就任意选出 $\frac {len} {2}$ 个对子放入.
若串长为奇,此时若 $0,1$ 的个数有一个为奇,就让它去作为中心的数,否则就任意选一个填在中心.
剩下的部分仍然任意选对子放入,时间复杂度 $O(n)$ .
1 | //%std |
C Minimize The Integer
从前往后考虑每一位,根据数的比较方式,只需要贪心地让当前这一位尽可能的小.
注意到一个奇数往前换,如果它的前面还有奇数,则它一定会被挡住,不能来到当前的这位,偶数同理.
于是当前的这位就只能取剩下的第一个奇数或者第一个偶数.
这就是一个归并排序的过程,时间复杂度 $O(n)$ .
1 | //%std |
D Salary Changing
二分答案 $k$ ,则需要算出至少有 $\frac{n+1}{2}$ 个人的薪水 $\ge k$ 时,最小的总薪水是否 $\le s$ .
每个人的薪水区间 $[l,r]$ 要么满足 $l>k$ ,要么满足 $r<k$ ,要么满足 $l\le k\le r$ .
对于前两种区间,显然都选它们的左端点作为薪水.
若薪水 $\ge k$ 的人数还不够,则还要将一部分 $l\le k\le r$ 的区间选取的薪水从 $l$ 调整为 $k$ .
实现时,可以先将所有区间按照 $l,r$ 为两个关键字排序,从后往前扫一遍即可验证.
时间复杂度 $O(n\log n+n\log \max r)$ .
1 | //%std |
E Voting
将所有人按照 $m_i$ 从小到大排序,依次考虑.
记录一个 $cnt$ ,表示当前已经投了票的人数,到第 $i$ 个人时,若 $n-i+cnt<m_i$ ,则在 $[1,i]$ 中必须有人要投票.
用一个小根堆维护还没有投票的所有人的 $p$ ,需要投票时,就弹出堆顶,更新答案和 $cnt$ .
一个人最多只会被弹出一次,时间复杂度 $O(n\log n)$ .
1 | //%std |
F Red-White Fence
容易得出一个图形的周长为 $2(mx+1+w)$ ,其中 $w$ 表示使用的白色板子数目.
$k$ 很小,可以直接去枚举用的红色板子的高度 $mx$ ,尝试将每个 $w$ 的方案数都算出来,加入对应贡献.
从高到低考虑每种长度的白色板子,从高度 $<mx$ 的白色板子开始计算.
若这种长度只有 $1$ 块,则只能选择不加,或者加在某一边,生成函数表示为 $(1+2x)$ .
若 $>1$ 块,则可以选择不加,或者加在某一边,或者两边都加,生成函数表示为 $(1+2x+x^2)=(x+1)^2$ .
那么这些生成函数之积就是 $(1+2x)^a\cdot (x+1)^{2b}$ 的形式,用二项式定理算出两个多项式,再用 $NTT$ 将它们乘起来.
最后利用维护的贡献 $O(1)$ 回答每个询问.
时间复杂度 $O(kn\log n+q)$ .
1 | //%std |