D. Training Session
给定n个互不完全相同的 ( x , y ) (x,y) (x,y)对,统计有几个三元组,满足 x x x互不相同或 y y y互不相同
https://codeforces.com/contest/1598/problem/D
题解:组合,正难则反,注意条件中的互不相同!
B. Frog Traveler
一开始在位置 n n n,对于每个位置,你可以向上跳 [ 0 , a i ] [0,a_i] [0,ai],但是到每个位置后,你会向下滑 b i b_i bi,问最少跳几次到达位置 0 0 0
https://codeforces.com/contest/1601/problem/B
题解:BFS-style DP,记
f
i
f_i
fi表示从
n
n
n到
i
i
i (还没滑下去)所需最小步数,从
n
n
n开始更新,显然先被更新到的就找到最小的了,又由于每个点
i
i
i能更新的点是
[
i
+
b
i
−
a
i
−
b
i
,
i
+
b
i
]
[i+b_i-a_{i-b_i},i+b_i]
[i+bi−ai−bi,i+bi],即从更后面开始往前的区间,所以整个更新过程的区间一定是不跳跃的,是从尾部逐渐推进的,所以满足单调性,可以
O
(
n
)
O(n)
O(n)解决
Tips: BFS-style DP,每个点只有1次机会去更新别人,如果更新的是区间,也可以线段树,但是这题区间连续于是就是
O
(
n
)
O(n)
O(n)了。实现的时候和BFS一样用队列存,先进先出。
C. Optimal Insertion
给定2个数列{a},{b},要求把b中的数字任意插入a中,也就是a的顺序不变,b的顺序可变。要求插入后逆序对最少,求之
https://codeforces.com/contest/1601/problem/C
题解 :逆序数,性质比较难发现,也就是每个
b
b
b找到自己局部最优位置的时候,一定可以达到全局最优。简单意会就是,小的数肯定更喜欢往前跑,大的数往后跑,自然就能保证
a
b
ab
ab交互的最优也是
b
b
b的最优(
b
b
b递增序)。简单证明by caoyang1123:假设
b
i
b_i
bi增大,然后它的最优位置反而左移,那么左边一定存在一些比当前
b
i
b_i
bi大的值,左移过了这些值才能更优,但是原来bi更小,因此左移过这些值对之前也更优,矛盾。
问题转化为找每个
b
b
b的最佳插入位置,我们记
p
i
p_i
pi表示插入到
a
p
i
a_{p_i}
api之前,所以
p
i
=
n
+
1
p_i=n+1
pi=n+1表示插到末尾。
1.显然我们按
b
b
b 顺序处理,不妨升序
2.考虑
b
i
+
1
b_{i+1}
bi+1 带来的改变量,只有
b
i
≤
a
≤
b
i
+
1
b_i \leq a \leq b_{i+1}
bi≤a≤bi+1 的
a
a
a 会产生影响,这样更新显然每个
a
a
a 只会出现一次(?)
3.考虑怎么影响,我们假设一开始是一个极小的数字,即每个
a
a
a都对后面位置有一个贡献。当
a
a
a大于等于
b
b
b的时候要去掉对后影响,
a
a
a大于
b
b
b的时候要加上对前影响,所以其实好麻烦,要两个指针。
总结:线段树+单调指针扫过去更新
法2:我们深度挖掘一下性质,考虑到如果找到了 b m i d b_{mid} bmid的位置 p m i d p_{mid} pmid那么其他数字只能在左右两边,所以可以尝试用分治法(类似快排),每层类似法1也是加加减减,但是是暴力重新统计
E. Arena
当前有 n n n个数,则每个数减 n − 1 n-1 n−1,此时若某个数小于等于 0 0 0则被淘汰,存活的 n ′ n' n′个人重复以上操作,给定 n n n和最大数字 k k k,初始数字要在 [ 1 , k ] [1,k] [1,k]之内,问有几种初始情况下,不会产生最终(不死的)胜利者
1 ≤ n , k ≤ 500 1 \leq n,k \leq 500 1≤n,k≤500
https://codeforces.com/contest/1606/problem/E
题解 :DP+组合,题目类型是比较显然的,考虑怎么设计状态。
第一种想法是直接基于组合的,如
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示
i
i
i个人,最大数字(且取到)
j
j
j,考虑能否
O
(
n
)
O(n)
O(n)地扫一遍
f
[
i
−
1
]
[
k
]
f[i-1][k]
f[i−1][k]并结合组合知识搞定,不过这道题显然不可以(?)
第二种想法是基于模拟的,这种一轮一轮的游戏就很适合用这种方法,显然除了上文的
i
,
j
i, j
i,j,转移时我们最关心的是小于等于
i
−
1
i-1
i−1的人有几个,记为
k
k
k。
则dp转移方向是
f
[
i
]
[
j
]
[
k
]
←
f
[
i
−
k
]
[
j
−
i
+
1
]
[
.
.
.
.
]
f[i][j][k] \leftarrow f[i-k][j-i+1][....]
f[i][j][k]←f[i−k][j−i+1][....]
结合组合知识:
f
[
i
]
[
j
]
[
k
]
=
∑
C
i
k
∗
(
i
−
1
)
k
∗
f
[
i
−
k
]
[
j
−
i
+
1
]
[
l
]
f[i][j][k]=\sum C_i^k*(i-1)^k*f[i-k][j-i+1][l]
f[i][j][k]=∑Cik∗(i−1)k∗f[i−k][j−i+1][l]
解释:谁死*死的时候是
[
1
,
i
−
1
]
[1,i-1]
[1,i−1]哪个值
然后我们惊喜的发现,这个
l
l
l非常没有存在感,直接合并就好了,或者直接O(n)记一下,每个
k
k
k直接用也是可以保证复杂度正确的
合并后即
f
[
i
]
[
j
]
=
∑
k
C
i
k
∗
(
i
−
1
)
k
∗
f
[
i
−
k
]
[
j
−
i
+
1
]
f[i][j]=\sum_k C_i^k*(i-1)^k*f[i-k][j-i+1]
f[i][j]=∑kCik∗(i−1)k∗f[i−k][j−i+1]
初值即游戏结束状态,
f
[
1
]
[
j
]
=
1
f[1][j]=1
f[1][j]=1或
f
[
1
]
[
j
]
[
0
]
=
1
f[1][j][0]=1
f[1][j][0]=1
(其实我不是很分得清到底是=n还是=1,实际上是=1,但是我太菜了,想不清楚)
D. Difficult Mountain
一开始有 n n n个人,爬山难度 d d d,爬山难度会改变,记之后的爬山难度为 d ′ d' d′。第 i i i个人可以爬上 d ′ ≤ s i d' \leq s_i d′≤si的山,但是第 i i i个人爬完后,爬山难度 d ′ = m a x ( d ′ , a i ) d'=max(d',a_i) d′=max(d′,ai),求最多能爬上去几个人
https://codeforces.com/contest/1602/problem/F
题解:感觉很贪心,我们故技重施,考虑两个人:若两个人都是 s > a s>a s>a,我们肯定希望把 s s s大的放后面;若两个人都是 s ≤ a s \leq a s≤a,如果二选一的话,我们肯定希望选前者,如果有可能两个都选的话,我们肯定希望 a a a大的在后;若一个是 a a a大,一个是 s s s大,如果其中是 s m a x ≥ a m a x s_{max} \geq a_{max} smax≥amax,显然是把 s m a x s_{max} smax放后面,完美衔接还不会更劣,如果是 s m a x < a m a x s_{max} < a_{max} smax<amax,显然还是把 s m a x s_{max} smax放前面,否则 s m a x s_{max} smax这样一个不会更劣的好人肯定没机会选上了,然后 a m a x a_{max} amax能不能取到,后面的人能不能接上那就不是这两个人考虑的事情了。综上,按 m a x ( s , a ) max(s,a) max(s,a)排序后模拟
D. Red-Blue Matrix
给 n ∗ m n*m n∗m的矩阵按行染色并按列划分成两部分,要求左边的红色都大于左边的蓝色,右边的红色都小于右边的蓝色。若可以,给出方案
n , m ≤ 5 e 5 , n m ≤ 1 e 6 n,m \leq 5e5,nm \leq 1e6 n,m≤5e5,nm≤1e6
https://codeforces.com/contest/1606/problem/D
题解:题目要求的方案是非常严格的,但也非常复杂不好处理,我们可以弱化条件!我们按照每行第一个数重排每一行,显然此时可能的染色只能是横切一刀,划分是竖切一刀,我们可以从四个角开始预处理就可以 O ( 1 ) O(1) O(1)判断方案是否合法,综上 O ( n l o g n + n m ) O(nlogn+nm) O(nlogn+nm)