Codeforces Round #709 (Div. 2) 游记 & 题解

8 篇文章 0 订阅
7 篇文章 0 订阅

游记

开场之后,凭借自己长时间对思维的训练,很快切掉了前五题;然后开始写代码。

吭之吭之,T1 切掉之后,T2 乱搞过不了,第一次自闭。最后竟然过了,于是开 了 T3 。

T3 直接二分图建立然后跑最大流就行了,但是不停地 WA ,心想这都能 WA?第二次自闭。然后发现自己竟然把 cnt \text{cnt} cnt 搞成了 1 1 1 ,然后改回来只有又超时了 ⋯ \cdots 第三次自闭。然后怀着信仰,加各种奇葩优化加速算法,最后发现自己最大流用的板子是假的 ⋯ ⋯ \cdots \cdots 然后就 A 了。

T4,T5 自己的做法都是线段树,考虑到 T5 只需要多维护一个单调栈,于是就写了 T5 。结果脑子非常不清爽,写了 40 \text{40} 40 分钟,比赛结束了还没写出来。中途还被 b6e0 \text{b6e0} b6e0 狠狠地羞辱嘲笑了一番,嘲笑了一番,第四次自闭

比赛结束之后看了看 T6 ,想了半天只云云出来一个 O ( n 4 ) O(n^4) O(n4) 的解法。第二天看到自己 Rating 掉了 5 5 5 点,第五次自闭

在学校想出来一个 T6 的线性解法,假了。回家路上搞出来一个严格 O ( n 3 ) O(n^3) O(n3) 的解法,又假了。回家开题解看不懂,第六次自闭

然后打算写代码,发现明天要月考,写不了代码,第七次自闭

七次自闭,菜鸡的本性啊。

T1

令输入的两个数分别为 n , m n,m n,m ,则答案为 n × m n \times m n×m

T2

乱搞题。

首先,我们找到序列中满足 a i > a i + 1 a_i >a_{i+1} ai>ai+1 i i i 的数量 c n t cnt cnt

①若 c n t cnt cnt n − 1 n-1 n1 ,则答案不可能为 1 1 1。更为具体地说,如果这个序列是一个等差数列,则答案为 0 0 0 ,否则是 − 1 -1 1

②若 c n t cnt cnt 0 0 0 ,与①同理 。
③若 0 < c n t < n − 1 0 < cnt < n-1 0<cnt<n1 ,我们先随意找到一个满足 a i ≤ a i + 1 a_i \le a_{i+1} aiai+1 i i i ,显然 c = a i + 1 − a i c=a_{i+1}-a_i c=ai+1ai ;然后再随意找到一个满足 a i > a i + 1 a_i > a_{i+1} ai>ai+1 i i i ,显然 m = a i + c − a i + 1 m=a_i+c-a_{i+1} m=ai+cai+1 。最后判断一下是否合法即可。

T3

网络流建模裸题。

T4

循环地删除,想到了什么?这不是一个线段树的经典套路吗;我们再维护一个循环链表,每次删除的时候在线段树内修改后继位置,当要找到删除的位置的时候直接线段树上二分就行了。

T5

显然可以 dp \text{dp} dp ,但是直接转移是 O ( n 2 ) O(n^2) O(n2) 的。怎么办呢?我们套路地使用单调栈,然后用线段树维护一个 ⌊ \lfloor 区间加,前缀查询最大值 ⌉ \rceil 的问题就行了。

最后时刻没能调出来 😦

T6

Solution

我们先通过 Floyd \text{Floyd} Floyd 跑出每一对节点之间的最短路径长度 d i , j d_{i,j} di,j

令第 i i i query \text{query} query 形如 ( f i , g i ) (f_i,g_i) (fi,gi) 。一种朴素的想法是,枚举一条无向边 ( u , v , w ) (u,v,w) (u,v,w) ,然后判断是否满足

d u , f i + w + d v , g i ≤ l i d_{u,f_i} + w +d_{v,g_i} \le l_{i} du,fi+w+dv,gili

直接做是 O ( n 4 ) O(n^4) O(n4) 的。考虑优化。


考虑枚举 u , v u,v u,v f i f_i fi 。注意在枚举过程中,我们并不需要知道具体的 i i i 的值,只需要知道某个询问端点 f i f_i fi 就行了。

我们需要判断是否存在 i i i 使得

d u , f i + w ( u , v ) ≤ l i − d v , g i d_{u,f_i} + w(u,v) \le l_i - d_{v,g_i} du,fi+w(u,v)lidv,gi

定义 P ( x , y ) P(x,y) P(x,y) 表示是否存在一个 i i i 满足 f i = x , g i = y f_i=x,g_i=y fi=x,gi=y ,令
g ( v , f i ) = max ⁡ i = 1 n { [ P ( f i , g i ) ] l i − d v , g i } g(v,f_i)=\max_{i=1}^n \{[P(f_i,g_i)] l_i-d_{v,g_i} \} g(v,fi)=i=1maxn{[P(fi,gi)]lidv,gi}

显然,如果对于 ( u , v , f i ) (u,v,f_i) (u,v,fi) 存在至少一个满足要求的 g i g_i gi ,当且仅当
d u , f i + w ( u , v ) ≤ g ( v , f i ) d_{u,f_i}+w(u,v) \le g(v,f_i) du,fi+w(u,v)g(v,fi)

于是现在关键在于预处理出所有的 g ( v , f i ) g(v,f_i) g(v,fi)

我们枚举 v v v f i f_i fi ,然后在桶内找到所有满足 P ( f i , g i ) = 1 P(f_i,g_i)=1 P(fi,gi)=1 的另一个端点 g i g_i gi 并更新 g ( v , f i ) g(v,f_i) g(v,fi)。由于每条路径对复杂度的贡献了均为 O ( n ) O(n) O(n),所以这一部分的复杂度是 O ( n 3 ) O(n^3) O(n3)

总步骤如下:
Floyd \text{Floyd} Floyd 处理出每一对节点的最短路;
② 预处理出所有的 g ( v , f i ) g(v,f_i) g(v,fi)
③ 枚举 u , v , f i u,v,f_i u,v,fi 并判断是否合法。

上述三个部分的时间复杂度均为 O ( n 3 ) O(n^3) O(n3) ,于是总复杂度为 O ( n 3 ) O(n^3) O(n3)

Summary

本题的关键在于,将“枚举 ( u , v ) (u,v) (u,v)” 转化为枚举 ( u , v , f i ) (u,v,f_i) (u,v,fi) ,从而平衡了复杂度,将其降低为 O ( n 3 ) O(n^3) O(n3)

然而自己并没有想到这一个东西,主要是从来没有见到过这样子的经典套路。但是不想找什么理由了,我就是菜得不得了,有什么好说的呢。

Code

咕咕咕

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值