2016暑期集训12C L国货物运输 HDU 5699 货物运输

L国货物运输

【问题描述】
公元2222年,L国发生了一场战争。
小Y负责领导工人运输物资。
其中有m种物资的运输方案,每种运输方案形如li, ri。表示存在一种货物从li到ri。
这里有n个城市,第i个城市与第i+1个城市相连(这里1号城市和n号城市并不相连),并且从i号城市走到i+1号或者从i+1号走到i号需要耗费1点时间。 由于高科技的存在,小Y想到了一种节省时间的好方案。在X号城市与Y号城市之间设立传送站,只要这么做,在X号城市走到Y号城市不需要耗费时间,同样的,从Y号城市走到X号城市也不需要耗费时间。
但是为了防止混乱,只能设立这么一条传送站。
现在这些运输方案同时进行,小Y想让最后到达目的地的运输方案时间最短。
在样例中,存在两条运输方案,分别是1号城市到3号与2号到4号,那么我们在2号城市与3号城市建立传送站,这样运输方案时间最长的只需要1点时间就可以了。
【输入格式】
多组测试数据
第一行两个整数n,m。
接下来m行,每行两个整数li, ri。(若li=ri, 则不需要耗费任何时间)
【输出格式】
一个数表示答案。
【样例输入】
5 2
1 3
2 4
【样例输出】
1
【样例说明】
【数据规模和约定】
1<=n, m<=1000000 1<=li, ri<=n
这道题首先具有二分性
但如何判定是个难点
我们设二分枚举的时间为x
当 x >= r[i]-l[i]时,肯定可以到达
当x < <script type="math/tex" id="MathJax-Element-614"><</script>r[i]-l[i]时,得通过L R 这传送站,花费时间abs(L-l[i])+abs(R-r[i])
当我们确定L的位置时,我们也可以确定R的范围
当L < <script type="math/tex" id="MathJax-Element-615"><</script>l[i] 时 R在 l[i]+r[i]-x-L r[i]-l[i]+x+L
当L >= l[i] 时 R在 r[i]-l[i]-x+L l[i]+r[i]+x-L
我们可以先枚举每一个运输,找出共同的R的范围
在确定枚举L的位置,确定R有解,即该时间下可以完成所有的运输

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int l[1000005],r[1000005];
int check(int x)
{
    int a=0,b=1e9,c=0,d=1e9;
    for (int i=1;i<=m;i++)
    {
        if (abs(r[i]-l[i])<=x) continue;
        a=max(a,l[i]+r[i]-x);
        b=min(b,l[i]+r[i]+x);
        c=max(c,r[i]-l[i]-x);
        d=min(d,r[i]+x-l[i]);
    }
    for (int i=1;i<=n;i++)
    {
        int L=max(i,max(a-i,c+i)),R=min(n,min(b-i,d+i));
        if (L<=R) return 1;
    }
    return 0;
}
int ef(int st,int ed)
{
    if (st==ed) return st;
    int mid=(st+ed)>>1;
    if (check(mid))
    {
        return ef(st,mid);
    }else{
        return ef(mid+1,ed);
    }
}
int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        int maxm=0;
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&l[i],&r[i]);
            if (l[i]>r[i]) swap(l[i],r[i]);
            maxm=max(maxm,r[i]-l[i]);
        }
        printf("%d\n",ef(1,maxm));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值