第五题:T5限速
标签:思维、数学
题意:开车在一条路上,从坐标
0
0
0开始,车的起始速度是
1
1
1,车每开出一单位的距离,可以选择速度不变、或将速度增加一个单位、或减少一个单位,车的速度不能低于
1
1
1。
车子将通过
n
n
n个限速点,第
i
i
i个测速点的坐标为
x
i
x_i
xi,限速为
L
i
L_i
Li,当通过最后一个限速点,结束旅程,求整个路程过程中,车子能够达到的最大速度是多少?
题解:需要先从后往前维护一下,降速情况下,通过每个限速点的最大速度,实际能否到达题目限制的
L
i
L_i
Li,还会受到两个位置坐标距离的影响。
比如两个坐标位置距离为
10
10
10,前一个位置的限速为
30
30
30,后一个位置的限速为
5
5
5,那么开到前一个位置就不能是
30
30
30,而应该是
15
15
15,这样才能保证能到后一个位置能降速到
5
5
5。
预处理好之后,从前往后遍历,维护一下通过第
i
i
i个限速点的最大可行速度,
c
[
i
]
=
m
i
n
(
c
[
i
−
1
]
+
x
[
i
]
−
x
[
i
−
1
]
,
L
[
i
]
)
c[i]=min(c[i-1]+x[i]-x[i-1],L[i])
c[i]=min(c[i−1]+x[i]−x[i−1],L[i])
以下为数学推导:
设
a
a
a为
x
i
−
1
x_{i-1}
xi−1到
x
i
x_i
xi之间加速路段,
b
b
b为
x
i
−
1
x_{i-1}
xi−1到
x
i
x_i
xi之间减速路段。
c
i
−
1
c_{i-1}
ci−1为第
i
−
1
i-1
i−1个点的可行速度,
c
i
c_i
ci为第
i
i
i个点的可行速度。
可知
a
+
b
=
x
i
−
x
i
−
1
a+b=x_i-x_{i-1}
a+b=xi−xi−1,
c
i
−
1
+
a
=
c
i
+
b
c_{i-1}+a=c_i+b
ci−1+a=ci+b
c
i
−
1
+
a
=
c
i
+
x
i
−
x
i
−
1
−
a
c_{i-1}+a=c_i+x_i-x_{i-1}-a
ci−1+a=ci+xi−xi−1−a
把
a
a
a移到左边:
2
a
=
c
i
−
c
i
−
1
+
x
i
−
x
i
−
1
2a=c_i-c_{i-1}+x_i-x_{i-1}
2a=ci−ci−1+xi−xi−1=>
a
=
(
c
i
−
c
i
−
1
+
x
i
−
x
i
−
1
)
/
2
a=(c_i-c_{i-1}+x_i-x_{i-1})/2
a=(ci−ci−1+xi−xi−1)/2
最大速度为
c
i
−
1
+
a
c_{i-1}+a
ci−1+a,所以可以求出在这个路程中的最大速度为
(
c
[
i
]
+
c
[
i
−
1
]
+
x
[
i
]
−
x
[
i
−
1
]
)
/
2
(c[i]+c[i-1]+x[i]-x[i-1])/2
(c[i]+c[i−1]+x[i]−x[i−1])/2
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 3e5 + 10;
ll n, x[N], L[N], c[N];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> x[i] >> L[i];
}
for (int i = n; i >= 2; i--) {
if (L[i] < L[i - 1]) {
ll d = (x[i] - x[i - 1]);
// 通过每个限速点的最大速度
L[i - 1] = min(L[i - 1], L[i] + d);
}
}
c[0] = 1;
ll ans = 1;
for (int i = 1; i <= n; i++) {
ll d = (x[i] - x[i - 1]);
// c[i]: 通过第i个限速点的最大可行速度
c[i] = min(c[i - 1] + d, L[i]);
ans = max(ans, (c[i] + c[i - 1] + d) / 2);
}
cout << ans;
return 0;
}