B. Mystic Permutation
题意:给定一个 [ 1 , n ] [1,n] [1,n] 的排列,要求你构造一个新的 [ 1 , n ] [1,n] [1,n] 的排列,使得这两个排列之间的任意一个相同位置的元素都不相同,且满足这个排列的字典序最小。 如果无法构造出这样的序列则输出 − 1 -1 −1
思路:如果全局的去思考的话可能不是那么好想。我们从小到大关注每一位,当前位只可能从未选过的数的最小值和次小值中选择,如果 a a a 当前位等于最小值,那只能放次小值,且次小值一定能放。这样就放置了前 n - 1 个元素。对于最后一个元素,如果冲突,那和 n - 1 个元素交换即可。
AC代码:https://codeforces.com/contest/1689/submission/163086563
C. Infected Tree
题意:给定一棵以 1 1 1 号节点为根的二叉树,总节点个数为 n n n。
现在 1 1 1 号节点感染了病毒,每一回合,你可以选择删除任意一个没有被病毒感染(尚未被删除)的点,这样就断开了它与其直接相连的点的关系,紧接着被感染的点都会去感染与该节点直接相连的节点。
询问最多可以有多少不被病毒感染的点,被删除的点不算做不被病毒感染的点
思路:定义 d p [ i ] dp[i] dp[i] 表示在以 i i i 为根的子树中,若 i i i 被感染病毒,最多能保留多少节点。
叶子节点,
d
p
[
u
]
=
0
dp[u] = 0
dp[u]=0 。
非叶子节点:
- 若有一个儿子,则 d p [ u ] = s i z e ( v ) − 1 dp[u] = size(v)-1 dp[u]=size(v)−1
- 若有两个儿子, d p [ u ] = max ( s i z e ( v 1 ) − 1 + d p [ v 2 ] , s i z e ( v 2 ) − 1 + d p [ v 1 ] ) dp[u] = \max(size(v_1)-1+dp[v_2], size(v_2)-1+dp[v_1]) dp[u]=max(size(v1)−1+dp[v2],size(v2)−1+dp[v1])
AC代码:https://codeforces.com/contest/1689/submission/163088978
D. Lena and Matrix
题意:给定一个 n × m n\times m n×m 的网格,每个格子上有黑白两种颜色。请你找到一个格子,使得它距离所有黑色格子的曼哈顿距离的最大值最小。
思路:转化为切比雪夫距离然后维护 x , y x,y x,y 的边界然后枚举答案即可。也可以曼哈顿距离拆项。
AC代码:https://codeforces.com/contest/1689/submission/163091521
E. ANDfinity
题意:给定一个长度为 n ( n ≤ 2000 ) n(n\leq 2000) n(n≤2000) 的数组 a a a ,如果 a i & a j > 0 a_i \& a_j > 0 ai&aj>0 则给 ( i , j ) (i,j) (i,j) 之前连边。你可以执行之下操作多次
选择一个数,给他加一或者减一(不能减成负数)。
问最少需要多少次操作,整个图是联通的。
题解:Codeforces Round #798 (Div. 2) D(枚举) E(构造)
思路:这道题的重点是 lowbit 。首先先考虑如何在 O ( n log n ) O(n\log n) O(nlogn) 时间内判连通,可以维护一个并查集,考虑每一位,都是 1 的数连边即可。
然后在都是正数的情况下,我们考察每一个数的 lowbit 。如果最大的 lb 只有一个,那么我们让这个数减一,可以发现低位全变为了 1,对于其他的数,由于 lb 比当前的数要小,因此当前数减 1 必然可以将数组连通。如果有 1 个以上最大的 lb ,在这些 lb 最大的数中,选一个减 1,选一个加 1。
AC代码:https://codeforces.com/contest/1689/submission/163096117