[USACO13FEB]Taxi G
题目描述
Bessie is running a taxi service for the other cows on the farm. The cows have been gathering at different locations along a fence of length M (1 <= M <= 1,000,000,000). Unfortunately, they have grown bored with their current locations and each wish to go somewhere else along the fence. Bessie must pick up each of her friends at their starting positions and drive them to their destinations. Bessie’s car is small so she can only transport one cow in her car at a time. Cows can enter and exit the car instantaneously.
To save gas, Bessie would like to minimize the amount she has to drive. Given the starting and ending positions of each of the N cows (1 <= N <= 100,000), determine the least amount of driving Bessie has to do. Bessie realizes that to save the most gas she may need to occasionally drop a cow off at a position other than her destination.
Bessie starts at the leftmost point of the fence, position 0, and must finish her journey at the rightmost point on the fence, position M.
长度为m的栅栏上,有n头牛需要坐车前往别的地方,起点和终点分别为a_i和b_i。现在一辆出租车从最左端0出发,要运送完所有牛,最后到达最右端m,求最小路程。出租车只能一次载一只牛。
输入格式
* Line 1: N and M separated by a space.
* Lines 2…1+N: The (i+1)th line contains two space separated
integers, s_i and t_i (0 <= s_i, t_i <= M), indicating the starting position and destination position of the ith cow.
输出格式
* Line 1: A single integer indicating the total amount of driving Bessie must do. Note that the result may not fit into a 32 bit integer.
样例 #1
样例输入 #1
2 10
0 9
6 5
样例输出 #1
12
提示
There are two cows waiting to be transported along a fence of length 10. The first cow wants to go from position 0 (where Bessie starts) to position 9. The second cow wishes to go from position 6 to position 5.
Bessie picks up the first cow at position 0 and drives to position 6. There she drops off the first cow, delivers the second cow to her destination and returns to pick up the first cow. She drops off the first cow and then drives the remainder of the way to the right side of the fence.
想法
画了几个图后,感觉好像是折返得越短促越好,即,尽量一前一后交替进行。这个想法被我抛弃。两组数轴上没有交集的线段集合,是互不相干的。其中一个之内,向前的个数和向后的个数也不确定。“一前一后”的想法不像正解。
线段伴随两个数据:起点和终点。能不能贪心地,优先选择某个数据小的?
下面的反例告诉我们,策略一定是和起点与终点都相关的。
那么想到用交换调整法,找出贪心策略。可是想了一下之后,我感觉写出来的式子会很复杂,没敢写下来看。
能不能像Luogu P6146 [USACO20FEB]Help Yourself G一样,一条一条地把线段加进来,并贪心地修正路径?想了想,应该不行。
贪心、排序不等式 - AC(补)
线段是一定要走全程的,车上有人的路程固定,要考虑的就只是空车的情况,也就是从一个终点到另一个起点的转换的路程了。
因此,也把原点算作一个终点,m算作一个起点。
如果大胆写出了式子,也可以看出这一点。
∑
(
∣
t
[
i
]
−
s
[
i
]
∣
+
∣
s
[
i
+
1
]
−
t
[
i
]
∣
)
=
∑
∣
t
[
i
]
−
s
[
i
]
∣
+
∑
∣
s
[
i
+
1
]
−
t
[
i
]
∣
\sum(|t[i]-s[i]|+|s[i+1]-t[i]|)=\sum|t[i]-s[i]|+\sum|s[i+1]-t[i]|
∑(∣t[i]−s[i]∣+∣s[i+1]−t[i]∣)=∑∣t[i]−s[i]∣+∑∣s[i+1]−t[i]∣.
那么,把线段合理地首位连接起来,只需要考虑这个的终点到那个的起点距离之和就行了。
事实上,“这个的终点”和“那个的起点”可以随便对应,只需保证形成一个大环就可以。
可以根据排序不等式,把起点和终点排序,一一对应。
然而,可能会形成多个环,如图:
此时就要思考,如何把所有环合并成一个环,也就是如何合并两个环。
这个问题我百思不得其解。看了题解才知道,送奶牛时,可以从起点带它,把它扔到途中,待会再捡回来,送到终点。
英文题面中强调了这一点。中文翻译虽然没明说,但是能看出来。
那么,可以合并任意两个有重叠部分的环,只需要把环A随便从某个地方切开,从那里接环B,又回到原来的位置,继续接环A。
而有趣的是,有一条虚拟线段,从m到0,它所在的环,与任何一个环都有重叠,可以与之合并。
int n, m;
ll s[MAXN], t[MAXN], ans;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%lld%lld", s + i, t + i);
ans += abs(s[i] - t[i]);
}
s[0] = m, t[0] = 0;
sort(s, s + n + 1); sort(t, t + n + 1);
for (int i = 0; i <= n; ++i) {
ans += abs(s[i] - t[i]);
}
printf("%lld\n", ans);
return 0;
}