試題 歷屆試題 區間移位(二分求最大值最小)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章