时间限制: 1Sec 内存限制: 128MB 提交: 24 解决: 6
题目描述
数轴上有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。
思路:二分枚举答案,对于这种要求所有求解量中最大的那个要最小的这种题,比如这道就是让区间移动最大的最小,也就是所有区间的移动距离都小于等于这个最小值。很明显是有贪心的成分,如果我们正着贪心,通过选哪个区间先移动来求得这个最小值考虑的情况太多。那我们枚举二分答案,假设最小值是x,然后我们算每个区间在这个移动幅度内能否覆盖整个要覆盖的范围,能得话就记录下答案,并且继续在左半部分二分寻求更小的答案。首先要将区间按右端点升序排列,这样贪心的原因,我的理解是这样,既然我们的已经从零覆盖到的最大位置,是从左开始一直向右扩展的,那么假设每个区间大小一样,那么怎么移动才能让所有的区间移动区间尽可能小呢?显然是按右端点从左向右移动覆盖,这样第一个区间移动后(假设左移),那么这个已经覆盖的最大位置就会向右移动,我们每次循环只要找到一个合适的区间就停止,在进行下一轮循环,直到这一轮循环一个符合条件的都找不到,因为一旦找到一个,这个已经覆盖的最大位置就变了,那么之前有可能有的通过移动x无法覆盖到最大位置的区间离新的最大位置更近了,而继续循环将无法循环到这个曾经不符和条件的区间。
代码;
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
int maxx=20000;
int n;
struct node
{
int l;
int r;
} no;
bool cmp(node a,node b)
{
if(a.r==b.r)return a.l<b.l;
return a.r<b.r;
}
vector<node>v;
int check(int x)
{
vector<node>w(v);
int last=0;
while(true){
int fu=0;
for(int i=0; i<w.size(); i++)
{int lenn=w[i].r-w[i].l;
if(w[i].l-x<=last&&w[i].r+x>=last){
fu=1;
if(w[i].l+x>=last){
last+=lenn;
}
else{
last+=(w[i].r+x-last);
}
w.erase(w.begin()+i);//找到一个就删一个
break;//只要找到一个就退出循环,因为last已经更新的,也就是往右移动了,需要重新从剩下的区间中再次择优选择。(关键之处2)
}
}
if(w.size()==0||fu==0)break;
}
return last>=20000;
}
int main()
{
while(~scanf("%d",&n))
{v.clear();
int ll,rr;
for(int i=0; i<n; i++)
{
scanf("%d%d",&ll,&rr);
no.l=ll*2;//为了不让移动的最小距离出现小数,所以所有区间都乘二,因为最小的移动距离就是两个区间相差一,两边区间各移动0.5,成二后就变成了1,覆盖的区间也就变成了0-20000
no.r=rr*2;
v.push_back(no);
}
sort(v.begin(),v.end(),cmp);
int l=0,r=20000;
double ans=0;
while(l<=r)//(关键之处1)
{
int mid=(l+r)/2;
if(check(mid))//符合条件就继续找更小的
{
r=mid-1;
ans=mid;
}
else
{
l=mid+1;
}
}
ans/=2.0;
cout<<ans<<endl;
// printf("%d% d %d %d",v[0].l,v[0].r,v[1].l,v[1].r);
}
}