bzoj3062[Usaco2013 Feb]Taxi

现在流行开滴滴车了,所以L老师每天晚上没事的时候,也想玩一玩,当然他是为了好玩,所以对所有乘客免费。
他每天晚上从八中出发,认为是0点,整个黄白路长度为M。1<=M<=10^9
有N家客人(1<=N<=10^5)想要坐车,
它们会告诉L老师它们在哪里以及它们的目的地。而L老师的车太小了,一次只能坐一个人。
为了省油,L老师发现它每次不见得要把客人直接送到它的目的地,可以在中途放下之后再来接(由于L老师是免费送人,所以客人们也就不计较这些了)
最后L老师想问,它从0号出发,接完所有的客人,最后到达M点最少要走多少路程?
输入
第一行给出N,M
接下来N行,每行描述一个客人的起点与终点

输出

如题

 

输入数据
2 10
1 7//认为是a牛
3 4//认为是b牛
输出
12
hint
abs(0-1)=1..空车状态
abs(1-4)=3..非空车从1走到4,经过3,将a牛放下,接到b牛,再走到4接b牛放下
abs(4-3)=1..空车状态,走到3接上a牛
abs(3-7)=4..非空车状态,走到7将a牛放下
abs(7-10)=3..空车状态
发现此处在算非空车时有以下两项即
abs(1-4)与abs(3-7)
这也我们常理中的
1到7的距离
3到4的距离
是等价的,总和为7


根据题意所说,我们可以在某个点放下一头牛a,换上另一个头牛b.将b送到目的地后,再回头来接a(在这个接的过程中,车是空的)所以走的距离可以分成两类
1:非空车
2:空车
则对于(1)的计算,明显等于每头牛的出发点到目标点的距离差。
如果我们希望结果最小,就是(2)的值尽可能小。
对于空车,其状态为从一个终点到一个起点。
由于牛要从0到走m
所以不妨认为0是一个终点,m是一个起点。

(可以假设一下车开到0点,所有牛下车,所以是一个终点,然后开到1这个起点来接牛)
于是起点序列是一个数组,终点序列也是一个数组。
如果我们希望从终点中选些点来,也起点中的点一一配对。然后所有差值最小的话,那一定是再这两个数列升序排列后,对应位置相减。如下所示

起点序列   终点序列

1---------------0

3--------------4

10-------------7

于是空车的距离为1+1+3=5,于是最终结果为12

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define inc(i,j,k) for(int i=j;i<=k;i++)
#define maxn 100010
using namespace std;

inline int read(){
    char ch=getchar(); int f=1,x=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int n,m,a[maxn],b[maxn]; long long ans;
int main(){
    n=read(); 
	m=read(); 
	inc(i,1,n)
	    a[i]=read(),b[i]=read(); 
	inc(i,1,n)
	    ans+=abs(a[i]-b[i]);
    a[++n]=m; 
	b[n]=0; 
	sort(a+1,a+n+1); 
	sort(b+1,b+n+1); 
	inc(i,1,n)
	     ans+=abs(a[i]-b[i]);
    printf("%lld",ans); 
	return 0;
}

  

posted @ 2020-11-21 22:26  我微笑不代表我快乐  阅读(19)  评论(0编辑  收藏  举报