Taxi bzoj-3062 Usaco13Feb
题目大意:有n个奶牛想坐出租车。第i头奶牛在起点a[i]等候,想坐出租车到b[i]。Bessie从0出车,车上只能坐一头奶牛。她必须完成所有奶牛的要求而且她必须从0到m。
注释:$1le nle 10^5$,$1le mle 10^9$,1$le$a[i],b[i]$le$m。Bessie可以不用将一头奶牛一次性从起点送到重点,也就是说她可以中途扔下奶牛。
想法:好题!完全没想到,看了题解之后还想了很久题解为什么对。我们将所有的起点扔进一个集合,并且将m扔进起点集合。又将所有的终点扔进一个集合,将0扔进终点集合。首先,我们先将答案加上所有的abs(b[i]-a[i]),然后我们对这两个集合(起点集合和重点集合)构造一个双射。每一种双射恰恰表明了每一种扔奶牛的方式(很好证明)。然后将起点集合和重点集合分别排序,对应双射为最优方案。(证明挖坑代填)
最后,附上丑陋的代码... ...
// luogu-judger-enable-o2 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=100010; int n,m,st[N],ed[N]; ll ans=0; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&st[i],&ed[i]); ans+=abs(st[i]-ed[i]); } st[n+1]=m; ed[n+1]=0; sort(st+1,st+n+2); sort(ed+1,ed+n+2); for(int i=1;i<=n+1;i++) ans+=abs(ed[i]-st[i]); printf("%lld ",ans); return 0; }
小结:好题。