BZOJ2280: [Poi2011]Plot
来源:互联网 发布:蒙古输入法软件下载 编辑:程序博客网 时间:2024/04/29 17:00
题目大意:给定n个点和m,要求把n个点分成m段,使得每段的最小覆盖圆的半径的最大值最小
肯定能想到要二分答案,然后看看怎么判定
对于每个点来说,需要找到序列中最远能到达的从他开始符合条件的点
但是因为最小圆覆盖需要随机打乱点才能保证时间复杂度,所以我们不能依次推出最小覆盖圆,那么能想到二分
但是每次检验是O(长度)的,而我们需要二分m次,直接二分可能会使时间复杂度变成O(logINF*NMlogN)
所以我们需要用到一些小技巧,就是先检验长度为1的方案,然后检验长度为2的方案,然后4,8.....直到找到一个不合法的k
然后我们紧接着在[k/2,k]这个区间里二分就可以了
因为这样这次搜索的二分上限为O(KlogN),而对答案的贡献至少为K,所以当对答案的贡献为N(即扫到最后)时,时间复杂度上限为O(NlogN)
所以总时间复杂度变成了O(NlogNlogINF)
PS:这题在POI上单点220s!!!!!!!BZOJ总时限300s差评!!害的我卡了好几发OJ,最后调了调eps,300.198s卡时过了....
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 100010#define eps 2e-8using namespace std;struct node{long double x,y;};long double sqr(long double x){return x*x;}long double dis(node x,node y){return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y));}node a[N],b[N];int n,m;node O;long double R;node jfc(long double a,long double b,long double c,long double d,long double e,long double f){long double y=(a*f-c*d)/(b*d-a*e);long double x=(b*f-c*e)/(a*e-b*d);return (node){x,y};}bool incircle(node x){if(dis(x,O)<=R+eps) return true;return false;}void solve(int l,int r){int i,j,k;for(i=l;i<=r;i++)b[i-l+1]=a[i];int nn=r-l+1;random_shuffle(b+1,b+nn+1);R=0;for(i=1;i<=nn;i++)if(!incircle(b[i])){O=b[i];R=0;for(j=1;j<i;j++)if(!incircle(b[j])){O.x=(b[i].x+b[j].x)/2;O.y=(b[i].y+b[j].y)/2;R=dis(O,b[i]);for(k=1;k<j;k++)if(!incircle(b[k])){O=jfc(b[i].x-b[j].x,b[i].y-b[j].y,(sqr(b[j].x)+sqr(b[j].y)-sqr(b[i].x)-sqr(b[i].y))/2,b[i].x-b[k].x,b[i].y-b[k].y,(sqr(b[k].x)+sqr(b[k].y)-sqr(b[i].x)-sqr(b[i].y))/2);R=dis(O,b[i]);}}}}int far(int st,long double limit){int i,j;for(i=1;;i++){solve(st,min(st+(1<<i)-1,n));if(R>limit+eps) break;if(st+(1<<i)-1>=n) return n;}int l=st+(1<<(i-1)),r=min(st+(1<<i)-1,n),mid;while(l<r){mid=(l+r)>>1;solve(st,mid);if(R>limit+eps) r=mid;else l=mid+1;}return l-1;}bool judge(long double limit){int i,j,tot=0;for(i=1;i<=n;i=j+1){if(tot==m) return false;j=far(i,limit);tot++;}return true;}int main(){/*freopen("wyk.in","r",stdin);freopen("wyk.out","w",stdout);*/scanf("%d%d",&n,&m);int i,j;double tmp1,tmp2;for(i=1;i<=n;i++){scanf("%lf%lf",&tmp1,&tmp2);a[i].x=tmp1;a[i].y=tmp2;}solve(1,n);long double l=0,r=R,mid;while(r-l>eps){mid=(l+r)/2;if(judge(mid)) r=mid;else l=mid;}printf("%.15lf\n%d\n",(double)l,m);j=1;for(i=1;i<=m;i++){if(j>n){puts("0 0");continue;}int tmp=far(j,l+eps);solve(j,tmp);printf("%.15lf %.15lf\n",(double)O.x,(double)O.y);j=tmp+1;}}
0 0
- 【POI2011】【BZOJ2280】Plot
- BZOJ2280: [Poi2011]Plot
- BZOJ 2280 Poi2011 Plot 二分答案+随机增量法
- [二分答案 随机增量法] BZOJ 2280 [Poi2011]Plot
- plot
- 【POI2011】 Meteors
- POI2011 题解
- [bzoj 2526]Poi2011 Inspection
- [bzoj 2525]Poi2011 Dynamite
- [BZOJ 2277]Poi2011 Strongbox
- 【BZOJ 2527】 [Poi2011]Meteors
- BZOJ 2529 Poi2011 Sticks
- BZOJ 2217 Poi2011 Lollipop
- 【POI2011】【BZOJ2527】Meteors
- bzoj2276【poi2011】Temperature
- BZOJ2527: [Poi2011]Meteors
- 2527: [Poi2011]Meteors
- bzoj2215: [Poi2011]Conspiracy
- bzoj1042[HAOI2008]硬币购物
- 关于webview需要知道的东西
- nyoj 133 子序列(尺取法+离散化)
- Java与JS互掉示例2
- HNNU 11656 错误的算法【 湖南省第十一届大学生计算机程序设计竞赛,模拟】
- BZOJ2280: [Poi2011]Plot
- C++ 复合类型(三)--数组vector、array
- 单选框(复选框)按钮样式
- Combination Sum
- php的pecl命令安装 mongodb模块的报错解决办法
- [BZOJ1042][HAOI2008]硬币购物 (DP+容斥原理)
- 4. JavaScript Debug Tips
- Kinect V2 开发环境搭建
- 从1 到 n 中 k 出现的次数