Codeforces729C Road to Cinema(贪心+二分)

  • 题目大意:在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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值