問題描述
數軸上有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;
}