【POI2011】【BZOJ2280】Plot

来源:互联网 发布:匈牙利命名法 数组 编辑:程序博客网 时间:2024/05/14 19:47

Description

给出一系列点p_1, p_2, … , p_n,将其分成不多余m个连续的段,第i段内求一个点q_i,使得q_i到这段内点的距离的最大值的最大值最小

Input

第一行,n m
下面n行,每行两个整数,表示p_i的x y坐标
1<=m<=n<=100000
坐标范围[-1000000,1000000]

Output

第一行,q_i到这段内点的距离的最大值的最大值的最小值
第二行,分成的段数k
下面k行,每行两个实数,表示q_k的x y坐标

All the real numbers should be printed with at most 15 digits after the decimal point.
Sample Input
7 2
2 0
0 4
4 4
4 2
8 2
11 3
14 2

Sample Output
3.00000000
2
2.00000000 1.76393202
11.00000000 1.99998199
HINT

wyx528提供SPJ

Source
二分一个半径,然后划分区间
划分时候倍增求区间长度否则T
我不知道求最小圆覆盖的时间复杂度是什么所以不会分析这题时间复杂度
但是从rank4-rank倒数做法都是一样的,时间差就在常数而已
但是我花160s A了这个题之后
有不知道哪里的傻逼偷了我的号密码
提交这个题又交了两发卡评测

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define eps 1e-10#define MAXN 100100using namespace std;int n,m,top,T=50;double R,l,r,mid;int ans[MAXN][2],cnt;struct Point{    double x,y;}s[MAXN],sta[MAXN],C;double sqr(double x){    return x*x;}double dis(Point a,Point b){    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}Point Mid(Point a,Point b){    return (Point){(a.x+b.x)/2,(a.y+b.y)/2};}Point cen(Point a,Point b,Point c)//三点求圆心 {    double x1=b.x-a.x,y1=b.y-a.y,x2=c.x-a.x,y2=c.y-a.y;    double r1=(sqr(x1)+sqr(y1))/2,r2=(sqr(x2)+sqr(y2))/2,d=x1*y2-x2*y1;    return (Point){a.x+(r1*y2-r2*y1)/d,a.y+(x1*r2-x2*r1)/d};}void calc(int l,int r)//对区间l,r的圆做最小圆覆盖 {    top=0;    for (int i=l;i<=r;i++)  sta[++top]=s[i];    for (int i=1;i<=top;i++)    swap(sta[rand()%i+1],sta[i]);    C=sta[1];R=0;    for (int i=1;i<=top;i++)    {        if (dis(C,sta[i])<=R+eps)   continue;        C=Mid(sta[1],sta[i]),R=dis(sta[i],C);        for (int j=1;j<i;j++)        {            if (dis(C,sta[j])<=R+eps)   continue;            C=Mid(sta[i],sta[j]),R=dis(sta[i],C);            for (int k=1;k<j;k++)                if (dis(sta[k],C)>R+eps)    C=cen(sta[i],sta[j],sta[k]),R=dis(sta[i],C);        }       }}bool check(double x)//确定划分的区间 {    int cut=0,num=0,l,r,mid,j;    for (int i=1;i<=n;i=cut+1)    {        for (j=1;i+(1<<j)-1<=n;j++)        {            calc(i,i+(1<<j)-1);            if (R>x+eps)    break;        }        cut=i;l=i+(1<<(j-1))-1;r=min(i+(1<<j)-1,n);        while (l<=r)        {            mid=(l+r)>>1;calc(i,mid);            if (R<x+eps)    cut=mid,l=cut+1;            else    r=mid-1;        }        num++;        if (num>m)  return 0;    }    return 1;}void get_ans(double x){    int cut=0,l,r,mid,j;    for (int i=1;i<=n;i=cut+1)    {        for (j=1;i+(1<<j)-1<=n;j++)        {            calc(i,i+(1<<j)-1);            if (R>x+eps)    break;        }        cut=i;l=i+(1<<(j-1))-1;r=min(i+(1<<j)-1,n);        while (l<=r)        {            mid=(l+r)>>1;calc(i,mid);            if (R<x+eps)    cut=mid,l=cut+1;            else    r=mid-1;        }        ans[++cnt][0]=i;ans[cnt][1]=cut;    }   }int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++)  scanf("%lf%lf",&s[i].x,&s[i].y);    calc(1,n);    r=R;    while (m>1&&r-l>eps&&T--)    {        mid=(l+r)/2;        if (check(mid)) r=mid;        else    l=mid;    }    printf("%.9f\n",r);    get_ans(r);    printf("%d\n",cnt);    for (int i=1;i<=cnt;i++)    {        calc(ans[i][0],ans[i][1]);        printf("%.9f %.9f\n",C.x,C.y);    }}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机显示系统空间不足怎么办 联系人存储已停止运行怎么办 荣耀note8听筒声音小怎么办 红米4x内存不足怎么办 安卓电视内存小怎么办 红米手机运行内存不足怎么办 红米手机存储空间不足怎么办 华为手机储存空间不足怎么办 大麦机顶盒遥控器丢了怎么办 大麦盒子总自动加软件怎么办 小米手机玩王者荣耀卡怎么办 荣耀8青春版信号差怎么办 华为mate8电池不耐用怎么办 华为4x内存小怎么办 发现手机被用过怎么办 华为p8手机声音小怎么办 手机指纹解锁密码忘了怎么办 华为p10黑色掉漆怎么办 金立手机导航信号弱怎么办 手机导航时gps信号弱怎么办 三星手机导航gps信号弱怎么办 小米5导航信号弱怎么办 华为手机导航gps信号弱怎么办 手机屏玻璃裂了怎么办 oppo音量键坏了怎么办 魅蓝手机屏幕碎了怎么办 手机钢化膜边缘有气泡怎么办 手机贴钢化膜边缘有气泡怎么办 苹果手机钢化膜边缘有气泡怎么办 手机膜里的水泡怎么办 膜贴好了有气泡怎么办 后档玻璃膜气泡怎么办 贴膜里面有灰尘怎么办 贴膜边缘不粘怎么办 贴膜时候的气泡怎么办 贴手机膜起泡了怎么办 手机膜起泡泡了怎么办 手机膜鼓起来了怎么办 贴膜中间有气泡怎么办 新车贴膜有气泡怎么办 贴手机膜进灰尘怎么办