Codeforces Round #733 (Div. 1 + Div. 2)
A
略
B
略
C
略
D
题意就是构造一个错位排列 (b),和 (a) 相同的位置尽量多。
设 (a_i) 有 (num) 种,答案只能为 (num/num-1)。首先给每个 (a_i) 随便配一个位置,如果只剩下一个位置且剩下的元素和位置标号相同,则方案需要修改:如果存在一个 (a_i) 有多个位置,随便换一个就一定可行了,答案依旧为 (num);否则,只能随便把一个 (a_i) 的匹配拆开,答案减一,然后一定存在一种方案。
E
分类讨论烦烦题。答案只能是 (0/1/n-1)。
1、若只有一种字符,随便排都一样,(f(t)=n-1)
2、存在某种字符只有一个,把它放在开头,(f(t)=0),并且后面随便,从小到大排即可
3、设最小的为 (x),如果 (x) 能在开头放两个,后面不能再出现 (xx),判断一下数量关系;否则只能放一个,第二个放次小的 (y),然后再分类:如果只有一个 (x),接下来就从小到大排;否则,如果有多于三种字符,可以从第三个位置开始放掉所有的 (x),然后接上第三大的 (z),之后贪心;如果只有两种字符,只能 (xyyydots yyxxxdots xx)。
F
对角线先别管,容斥一下做 (4) 遍就好了。大体思路就是先对行预处理然后枚举列的情况进行容斥(略)
G
构造毒毒题。设 (a) 中 (1) 的数量为 (c)。我们只考虑让 (c+1) 段连续的 (0) 的个数组成的数列 (p) 相同(记为 (p_0,p_1,p_2dots p_c))。先把 (0/1) 数目对不上的明显无解判掉。
1、(k=0),啥也改不了,比较一下就好了
2、(k=c),只能改变 (p[1,c-1]) 顺序并让 (p_0,p_c) 重新分配,特判
3、(1le k<c),此时考虑进行一对操作:翻转 (p[0,k]),再翻转 (p[1,k+1]),前 (k+1) 个变成 (p_k,p_{k+1},p_0,p_1dots p_{k-1}),也就是把后两个滚到前面了。若 (k+1) 为奇数,进行 (k) 组操作后,原本的每个 (p_i) 都会到 (p_{k+1}) 一次,而我们就趁这个机会把 (p_i) 合并到 (p_0) 中。于是一番操作后,(p[0,k+1]) 中的所有 (0) 都到了 (p_0) 里。对于 (k+1) 之后的,显然可以通过 (c-k) 次翻转把他们都弄到前 (k+1) 里。那么我们就通过 (le 2cle2n) 次操作把 (a) 的所有 (0) 都堆到了最前面。设这个过程为 (A),设把 (b) 中所有 (0) 堆到最前面的过程为 (B),操作可逆,那么我们只要正着输出 (A),倒着输出 (B) 就是最终的方案。对于 (k+1) 为偶数的情况,奇偶相对独立,做法类似。
H
一步一步来:
1、考虑逆过程,即从 (a_n) 到 (a_1) 的顺序填,以为这样不会覆盖,更容易计算。每次加上一个数只能在头和尾的位置。
2、不要管当前人在哪里,只要让出现在格子上的数之间有足够的距离
3、最优方案中出现在格子上的数,满足两个条件:是 (a_n) 或在 (b) 的 (LIS) 中。
4、分 (a_n) 在不在 (LIS) 中做两边。设 (f_L(k,i)) 表示 ([i,n]) 中选了 (k) 个,(i) 被选了且被加在最左边,(LIS) 右端的最小值是多少,(f_R(k,i)) 定义类似。然后在 (f_L,f_R) 之间转移,可以用线段树优化为 (knlog n)。
5、最后发现 (b) 数组由 (a) 的一个上升序列和一个下降序列拼成,而 (a) 随机,那么 (k) 的数量级为 (sqrt{n}),复杂度 (O(n^{1.5}log n))