游记
开场之后,凭借自己长时间对思维的训练,很快切掉了前五题;然后开始写代码。
吭之吭之,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 n−1 ,则答案不可能为 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<n−1 ,我们先随意找到一个满足
a
i
≤
a
i
+
1
a_i \le a_{i+1}
ai≤ai+1 的
i
i
i ,显然
c
=
a
i
+
1
−
a
i
c=a_{i+1}-a_i
c=ai+1−ai ;然后再随意找到一个满足
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+c−ai+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,gi≤li
直接做是 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)≤li−dv,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)]li−dv,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
咕咕咕