任重而道远
【问题描述】
燕子飞到温暖的南方去了。
分别后的十年里,小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。
【输出格式】
输出一行,一个整数,表示可能的最小的 任务所需时间最大值。
【输入输出样例】
bricks.in |
bricks.out |
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
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
const int oo = 1e9;
struct Node {
int l, r;
}nd[N];
int n, m;
bool check (int sww) {
int max1 = oo, max2 = oo;
int min1 = -oo, min2 = -oo;
for (int i = 1; i <= m; i++) {
if (nd[i].r - nd[i].l <= sww) continue;
max1 = min (max1, nd[i].r + nd[i].l + sww);
max2 = min (max2, nd[i].r - nd[i].l + sww);
min1 = max (min1, nd[i].r + nd[i].l - sww);
min2 = max (min2, nd[i].r - nd[i].l - sww);
}
return min1 <= max1 && min2 <= max2;
}
int main () {
freopen ("bricks.in", "r", stdin);
freopen ("bricks.out", "w", stdout);
scanf ("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int l, r;
scanf ("%d%d", &l, &r);
if (l > r) swap (l, r);
nd[i] = (Node) {l, r};
}
int lf = 0, rg = n;
while (lf < rg) {
int mid = lf + rg >> 1;
if (check (mid)) rg = mid;
else lf = mid + 1;
}
printf ("%d", lf);
return 0;
}