问题描述
数轴上有n个闭区间D1,…,Dn。其中区间Di用一对整数[ai, bi]来描述,满足ai < bi。已知这些区间的长度之和至少有10000。所以,通过适当的移动这些区间,你总可以使得他们的“并”覆盖[0, 10000]——也就是说[0, 10000]这个区间内的每一个点都落于至少一个区间内。
你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。
具体来说,假设你将Di移动到[ai+ci, bi+ci]这个位置。你希望使得maxi |ci| 最小。
输入格式
输入的第一行包含一个整数n,表示区间的数量。
接下来有n行,每行2个整数ai, bi,以一个空格分开,表示区间[ai, bi]。保证区间的长度之和至少是10000。
输出格式
输出一个数,表示答案。如果答案是整数,只输出整数部分。如果答案不是整数,输出时四舍五入保留一位小数。
样例输入
2
10 5010
4980 9980
样例输出
20
样例说明
第一个区间往左移动10;第二个区间往右移动20。
样例输入
4
0 4000
3000 5000
5001 8000
7000 10000
样例输出
0.5
样例说明
第2个区间往右移0.5;第3个区间往左移0.5即可。
输入样例
4
1000 3000
0 5000
7000 10000
8000 9000
输出样例
1000
排序按右区间排,输入的时候要处理一下,要乘以2,这样结果是0.5的时候好算一些,因为两个整数区间的移动不可能移动0.2,0.3这样的。二分判断函数要注意有的区间可以先不用。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10000;
const int inf=0x3f3f3f3f;
struct node{
int x,y;
}s[N];
int n;
bool cmp(node a,node b){
return a.y<b.y;
}
int judge(int x){
int t=0,i,j=0,v[N]={0},idx=0;
for(i=0;idx<20000&&i<n;i+=(j==i),j=i){
while(j<n&&(v[j]||idx+x<s[j].x)) j++;//有的区间可以暂时不用
if(j>=n) return 0;
v[j]=1;
if(s[j].x<idx){//上次位置比下一个区间左位置大
idx=s[j].y+min(x,idx-s[j].x);
}
else {
idx=s[j].y-(s[j].x-idx);
}
}
return idx>=20000;
}
int main()
{
int m,i,j,x,y;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d %d",&s[i].x,&s[i].y);
s[i].x*=2;s[i].y*=2;
}
sort(s,s+n,cmp);
int l=0,r=20000;
while(l<=r){
int mid=(l+r)/2;
if(!judge(mid)){
l=mid+1;
}
else {
r=mid-1;
}
}
cout<<l/2.0;
return 0;
}