Codeforces Round #775 (Div. 1, based on Moscow Open Olympiad in Informatics)(CF1648)

A

签到题,略。

B

Description

给定一个长度为\(n\)的序列,要求判断是否满足\(\forall x,y\in \{a_i\}, x>y\),有\(\lfloor x/y\rfloor \in \{a_i\}\)

\(\sum n \le 10^6, c = \max \{a_i\}\le 10^6\)

Solution

对于序列中的每个数\(y\),枚举\(z\),找到区间\([x_l,x_r]\)满足\(\forall x\in [x_l,x_r]\)\(\lfloor x/y\rfloor = z\),如果\(\exist a_i \in [x_l,x_r]\)且序列中没有\(z\),则不满足要求。

枚举每个数倍数的时间复杂度是\(O(c\log c)\)的。

C

Description

给定两个数组\(s,t\),对\(s\)进行排列,要求\(s\)字典序小于\(t\),问排列方案数。

\(|s|,|t|\le 2\times 10^5\)\(s_i,t_i \le 2\times 10^5\)

Solution

对于\(s\)的每个位置\(i\),将\(s_1\dots s_{i-1}\)依照\(t\)填满,第\(i\)位填一个比\(t_i\)小的数,后面的就可以乱填了。

\(s_i\dots s_n\)剩下可以填的数里不同的数的出现次数为\(a_{x_1}, a_{x_2}, a_{x_3}, \dots\),假设第\(i\)位填入\(x_1\),那么方案数为

\[\frac{(-1+\sum a_x)!}{(a_{x_1}-1)!\prod a_{x_i}!}=\frac{(-1+\sum a_x)!}{\prod a_{x_i}!}\times a_{x_1} \]

那么所有小于\(t_i\)\(x_i\)填入\(s_i\)位置的方案数为

\[\frac{(\sum a_x)!}{\prod a_{x_i}!} \times \sum_{x_i < t_i} a_{x_i} \]

维护乘号前面的分母,再用树状数组处理乘号后面的部分即可。

D

Description

有一个\(3\times n\)的方格,要从\((1,1)\)走到\((3,n)\),每次只能向坐标增加的方向移动一单位。每个格子有一个分数\(a_{i,j}\)(可能为负),走到该格子即得到这个分数。

第二行的格子一开始都是禁止通行的,有\(q\)条信息\((l_i,r_i,k_i)\)\(k_i>0\)),表示你可以让自己的分数减去\(k_i\)使得第二行的\((l_i,r_i)\)允许通行。要求最大化最终分数。

\(n,q \le 500000\)

Solution

\(a_{i,j}\)在第二维上的前缀和是\(s_{i,j}\),我们需要找到连续的一段\([l,r]\),用一些区间去完全覆盖它,分数即为:

\[s_{1,l} + (s_{2,r} - s_{2,l-1}) + (s_{3,n} - s_{3,r-1}) - K(l,r) = (s_{1,l} - s_{2,l-1}) + (s_{2,r} - s_{3,r-1}) + s_{3,n} - K(l,r) \]

我们对于每个区间找到区间内\((s_{1,i}-s_{2,i-1})\)最大的那个\(i\)作为左端点\(l\),然后以DP的形式往后面接区间,即对于每个区间的右端点,将区间\([l\color{red}{-1},r-1]\)内的右端点的信息选一个最大的转移过来,这个过程可以用线段树实现。

于是我们得到了对于每一个区间右端点,往前选取一个左端点的最大分数\(f_i\),并设\(s_{2,r}-s_{3,r-1}=g_r\)

对于每一个区间\([l,r]\),找到\(i,j\)满足\(l \le i \le j \le r\)\(i\)为上一个区间的右端点,\(j\)为整个第二行通行区域的右端,故取\(f_i+g_j+k_{l,r}\)作为分数。

为什么不能直接对于每个区间找到区间内最大的\(g_i\)加到\(f\)上:不能保证右端点\(i\)一定在之前取的左端点的右边。

注意只开通一个区间的情况需要另外算。

E

Description

给定一张无向带权联通图\(G = (V, E)\),一条路径的通行费用为路径上的最大边权。

构造\(G\)的补图\(G'\)(数据保证\(G'\)联通),边\((u,v)\)的边权为\(G\)中路径\((u,v)\)的最小费用。

构造\(G'\)的补图\(G''\),边\((u,v)\)的边权为\(G'\)中路径\((u,v)\)的最小费用。

\(G''\)每条边的边权。(\(n,m\le 200000\)

Solution

“路径上的最大边权”\(\Rightarrow\)最小生成树

\(G'\)的边数太多,我们考虑先求\(G'\)的MST,然后求\(G''\)的MST,最后在\(G''\)的MST上查询每个点对的费用即为答案。

以下是Neal_lee的解释orz:

你先求出原图建重构树叶子的dfs序,那么边 (u,v) 在补图 mst 上的必要条件是:degree(u) + degree(v) >= abs(rank(u) - rank(v)) - 1

rank(u) 是点 u 在 dfs 序列上的位置

如此条件不满足,则在 rank(u) 到 rank(v) 之间必然存在一个点,和 u,v 都有连边,而 u,v 向这个点连边是更优的。

所以有 2max(degree(u), degree(v)) >= abs(rank(u) - rank(v) - 1),于是可以枚举 degree 较大的点(不妨是 u),rank(v) 在区间 [rank(u) - 2degree(u) - 1, rank(u) + 2degree(u) + 1] 中,可以发现可行的点对数量是 O(m) 级别的。

pre 和 nxt 是 dfs 序的链表,可以发现对于前面的 u,要两边都完整的枚举才不会漏,可能会有重复,但是根据 kruskal 显然不会影响结果。

posted @ 2022-03-17 11:15  Hany01  阅读(59)  评论(0编辑  收藏  举报