题目大意:在tmin内到达电影院,路程从0至s,途中存在加油站,加油不需要时间,给定一批车辆,求出可以准时到达电影院的车中租金最少的那一个。
主要思路:因为加油站以无序的顺序给出,所以要将加油站位置进行排序,得出各加油站之间的距离。所使用的车辆应具备以下两个特点:
- 车能够完成任务,这需要该车油箱的容量可以跑完任意一个加油站之间的路程,并且能在tmin之内跑完全程。由于加油不需要费用和时间,从贪心的角度来讲,我们自然要在两个加油站之间耗完所有的油,能加速行驶的就加速行驶,这样就可以在最短的时间内跑完这一路程。如果车的载油量可以在完全加速行驶的情况下行驶完某段路程,显然就要这么做,此时容量L>=2delta(s);如果不能行驶过这段路程,即L小于delta(s),直接输出-1;如果有一段加速行驶一段匀速行驶,即s<=L<2delta(s),则分别设出各模式下行驶时间列方程组求解,此时可得通过这段路程的最短时间3delta(s)-L。最后进行累加比较总时间即可。
- 所用租金最小,这个在检验完所有的车之后取最小值即可。
算法实现:由于车数的数据规模达到了2*10^5,显然不能直接顺序查找一个个进行检验,可以使用二分提高时间效率。现将车按容量从小到大进行排序,二分检验,即可达到目的。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<string>
#include<set>
using namespace std;
const int maxn=200005;
int n,k,s,t,flag=0;
struct node
{
int c,v;
node (int c=0,int v=0):c(c),v(v){}
bool operator < (const node &a) const
{
return v<a.v;
}
};
node car[maxn];
int ki[maxn],del[maxn];
void init()
{
scanf("%d%d%d%d",&n,&k,&s,&t);
for (int i=1;i<=n;++i)
{
int c,v;
scanf("%d%d",&c,&v);
car[i]=node(c,v);
}
for (int i=1;i<=k;++i)
scanf("%d",&ki[i]);
sort(ki+1,ki+k+1);
del[0]=ki[1];
for (int i=1;i<=k-1;++i)
del[i]=ki[i+1]-ki[i];
del[k]=s-ki[k];
}
bool check(int nw)
{
int l=car[nw].v,tim=0;
for (int i=0;i<=k;++i)
{
if (2*del[i]<=l)
tim+=del[i];
else if (del[i]>l/2 && del[i]<=l)
tim+=(3*del[i]-l);
else return 0;
}
if (tim<=t)
{
flag=1;
return 1;
}
else return 0;
}
int py=0;
node ys[maxn];
int main()
{
init();
sort(car+1,car+n+1);
int l=1,r=n;
while (l<=r)
{
int mid=(l+r)/2;
if (check(mid))
r=mid-1;
else l=mid+1;
}
int std=car[l].v;
for (int i=1;i<=n;++i)
if (car[i].v>=std)
ys[++py]=car[i];
if (!flag)
{
printf("-1");
return 0;
}
int ans=2147483647;
for (int i=1;i<=py;++i)
ans=min(ans,ys[i].c);
printf("%d",ans);
return 0;
}