题目描述
燕子飞到温暖的南方去了。
分别后的十年里,小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;
}