2015.6.24 XJOI T1.不可视境界线

来源:互联网 发布:网站推广工作是seo吗 编辑:程序博客网 时间:2024/05/16 09:06

背景:

ZxrtX0IEEJCABCUhAAr1Y4NEMtL24Q9V0CUhAAhK

题目描述:

 

AMEQHlEbONAWAAAAAElFTkSuQmCC

输入格式:

543PDPxEEAAAQQQQAABowRo6IwqJ2EQQAABBBBAw

输出格式:

wGn+ZzdFBPBAgAAAABJRU5ErkJggg==

样例输入:

41 02 03 04 0

样例输出:

2.0000

数据范围:

wOPI63ulvVR5gAAAABJRU5ErkJggg==

时间限制:

1s

 

空间限制:

512MB


考试的时候只想到了cdq分治...没想到b的处理方法所以写了40分的结果拼上去的暴力挂了只剩下3 4的20分了

其实这题cdq分治的确可做

首先题目那个-a是忽悠你的。可以直接去掉

那么转移方程就是f[i]=min(f[i],sqrt(f[j]*f[j]+(a[i]-a[j])*(a[i]-a[j]))

我们把a[i]降序排序

然后移项后如果j>k j比k对于i优的话,那么满足((f[j]*f[j]+a[j]*a[j])+(f[k]*f[k]+a[k]*a[k]))/(2*(a[j]-a[k]))>a[i]

我们cdq分治处理左右区间。保证转移右区间的时候左区间已经转移完毕

然后左区间按照a降序,右区间按照b降序

这样就可以在枚举到右区间某个数的时候把可行左区间加入队列

然后对已经加入左区间的斜率二分就可以了

#include<cmath>#include<queue>#include<cstdio>#include<algorithm>using namespace std;struct enemy{     double a,b;     double f;     int p;}x[100001],tx[100001];int n;double f[100001];int q[100001];inline bool cmp1(enemy x,enemy y){     return x.b>y.b;}inline bool cmp2(enemy x,enemy y){     return x.a<y.a;}inline double getk(int j,int k){ if(j==0&&k==0)      return -1;     return ((x[j].f*x[j].f+x[j].a*x[j].a)-(x[k].f*x[k].f+x[k].a*x[k].a))/(double(2)*(x[j].a-x[k].a));}inline void cdq(int ll,int rr){     if(ll!=rr)     {          int mid=(ll+rr)/2;          int i;          int p1=ll-1,p2=mid;          for(i=ll;i<=rr;i++)          {               if(x[i].p<=mid)               {                    p1++;                    tx[p1]=x[i];               }               else               {                    p2++;                    tx[p2]=x[i];               }          }          for(i=ll;i<=rr;i++)               x[i]=tx[i];          cdq(ll,mid);          sort(x+mid+1,x+rr+1,cmp1);          int r=0;          int pp=ll;          for(i=mid+1;i<=rr;i++)          {               while(x[pp].a>=x[i].b&&pp<=mid)               {                    while(1<r&&getk(q[r],q[r-1])<getk(pp,q[r]))                         r--;                    r++;                    q[r]=pp;                    pp++;               }               int l0=2,r0=r;               while(l0<=r0)               {                    int mid=(l0+r0)/2;                    if(getk(q[mid],q[mid-1])>=x[i].a)                         l0=mid+1;                    else                         r0=mid-1;               }               if(r0!=0)                    x[i].f=min(x[i].f,sqrt(x[q[r0]].f*x[q[r0]].f+(x[q[r0]].a-x[i].a)*(x[q[r0]].a-x[i].a)));          }          cdq(mid+1,rr);          p1=ll;  p2=mid+1;          int p=ll-1;          while(p1<=mid&&p2<=rr)          {               if(x[p1].a>x[p2].a)               {                    p++;                    tx[p]=x[p1];                    p1++;               }               else               {                    p++;                    tx[p]=x[p2];                    p2++;               }          }          while(p1<=mid)          {               p++;               tx[p]=x[p1];               p1++;          }          while(p2<=rr)          {               p++;               tx[p]=x[p2];               p2++;          }          for(i=ll;i<=rr;i++)               x[i]=tx[i];     }}inline void solve2(){     cdq(1,n);     int i;     for(i=1;i<=n;i++)          if(x[i].p==n)               break;     printf("%.4lf\n",x[i].f);}int main(){     scanf("%d",&n);     int i;     bool flag=true;     for(i=1;i<=n;i++)     {          scanf("%lf%lf",&x[i].a,&x[i].b);          x[i].p=i;          if(x[i].b==0)               x[i].f=x[i].a;          else               x[i].f=1000000000;          if(x[i].b!=0)               flag=false;     }          solve2();     return 0;}


0 0
原创粉丝点击