问题 N: 搬砖

题目描述

燕子飞到温暖的南方去了。
分别后的十年里,小N孤身在家乡生活,迫于生计而找了份搬砖的工作(等等这什么鬼)。
共有n个工地,第i个工地和第i+1个直接相连(1<=i<n),工地1和n并不直接相连。
从工地i走到i+1或者从i+1走到i都需要耗费1点时间。
有m个运输任务,第i个要求小N把砖头从工地L_i运到R_i。
天才的小N有了个绝妙的主意,假如在工地X和Y之间搞个传送站,那么在X可以直接不需要时间地到Y(Y到X也一样)。
因为预算限制,小N最多建一个传送站。
小N想通过合理地放置传送站,使得所有运输任务所需时间的最大值最小。

输入

第一行两个整数n,m,分别表示n个工地,m个运输任务。
接下来m行,其中第i行俩整数L_i,R_i。

输出

输出一行,一个整数,表示可能的最小的 任务所需时间最大值。

样例输入

5 2
1 3
2 4

样例输出

1

提示

对于前15%的数据,保证n,m<=200
对于接下来10%的数据,保证n<=50,m<=10^5
对于接下来10%的数据,保证n<=1000,m<=1000
对于接下来35%的数据,保证n,m<=10^5,
对于100%的数据,保证n<=10^8,m<=10^5

 

ps: 今天训练赛,看某签到题前缀写着动态规划,嗯呵,告辞,我选择搬砖——然后搞了俩小时才把搬砖A了,菜的真实。回头看前面的动态规划…水的一批。

敲黑板划重点:小N想通过合理地放置传送站,使得所有运输任务所需时间的最大值最小。 使得所有运输任务所需时间的最大值最小。

对于每次搬砖来说,从 l -> r 两种可能,一种时间 r-l ,另一种,假设 传送站为 i -> j ,那么 所需时间为 | i - l | + | j - r |。

(其实到这步已经结束了,就是个矩形而已)

乱搞一下,

i + j = l + r - time,  i + j = l + r + time。

j - i = r - l - time,j - i = r - l + time。

所以:

二分枚举最大时间,

                                   ——我还是粘代码吧。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3fll
#define pi acos(-1.0)
#define ms(a,b) memset(a,b,sizeof(a))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
using namespace std;
typedef long long ll;
ll qpow(ll x, ll y, ll mod){ll s=1;while(y){if(y&1)s=s*x%mod;x=x*x%mod;y>>=1;}return s;}
//ll qpow(ll a, ll b){ll s=1;while(b>0){if(b%2==1)s=s*a;a=a*a;b=b>>1;}return s;
 
const int mod = 1e9+7;
const int maxn = 1e5+5;
 
struct node{
    int l,r;
}a[maxn];
 
int n, m;
 
int judge(int x)
{
    int ij = inf, ij_ = 0;    //j+i+x, j+i-x;
    int j_i = inf, j_i_ = 0;  //j-i+x, j-i-x;
    for(int i=1;i<=m;i++)
    {
        if(a[i].r - a[i].l > x)
        {
            ij = min(ij,a[i].r + a[i].l + x);
            ij_ = max(ij_,a[i].r + a[i].l - x);
            j_i = min(j_i,a[i].r - a[i].l + x);
            j_i_ = max(j_i_,a[i].r - a[i].l - x);
        }
    }
    if(ij>=ij_ && j_i>=j_i_) return 1;
    return 0;
}
 
int main()
{
    FAST_IO;
    cin>>n>>m;
    int l, r, mid;
    for(int i=1;i<=m;i++)
    {
        cin>>l>>r;
        if(l>r) swap(l,r);
        a[i].l = l;
        a[i].r = r;
    }
    l = 0, r = 1e8+9;
    while(l<=r)//run : time
    {
        mid = (l+r)/2;
        if(judge(mid)) r = mid-1;
        else l = mid+1;
        //cout<<"--"<<endl;
    }
   // cout<<l<<" "<<(r)<<endl;
    cout<<(r+1)<<endl;
 
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值