[loj2586]选圆圈

Posted pywbktda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[loj2586]选圆圈相关的知识,希望对你有一定的参考价值。

根据圆心建一棵kd-tree,然后模拟题目的过程,考虑搜索一个圆
剪枝:如果[与包含该子树内所有圆的最小矩形]都不相交就退出
然而这样的理论复杂度是o(n^2),所以会被出题人卡了
但是如果将坐标系旋转45度,对于(x,y),变为$((x.x-y.x)/\sqrt2,(x.x+y.x)/\sqrt2)$
然后因为可能相切,精度要求高,eps大约要取1e-3
技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 3000005
 4 #define k (l+r>>1)
 5 #define s (sqrt(2))
 6 #define eps (1e-3)
 7 #define sqr(x) (1LL*(x)*(x))
 8 int n,t,id[N],ans[N],ls[N],rs[N];
 9 struct P
10     double x,y;
11 mn[N],mx[N];
12 struct ji
13     int r,id;
14     P a;
15     bool operator < (const ji &p)
16         if (t)return a.x<p.a.x;
17         return a.y<p.a.y;
18     
19 a[N];
20 bool cmp(int x,int y)
21     return (a[x].r>a[y].r)||(a[x].r==a[y].r)&&(a[x].id<a[y].id);
22 
23 P rotate(P x)
24     return P(x.x-x.y)/s,(x.x+x.y)/s;
25 
26 double dis(P x,P y)
27     return sqr(x.x-y.x)+sqr(x.y-y.y);
28 
29 double calc(int t,P x)
30     P y;
31     if (x.x<mn[t].x)y.x=mn[t].x;
32     else
33         if (x.x<=mx[t].x)y.x=x.x;
34         else y.x=mx[t].x;
35     if (x.y<mn[t].y)y.y=mn[t].y;
36     else
37         if (x.y<=mx[t].y)y.y=x.y;
38         else y.y=mx[t].y;
39     return dis(x,y);
40 
41 void up(int l,int r)
42     mn[k].x=min(mn[ls[k]].x,mn[rs[k]].x);
43     mn[k].y=min(mn[ls[k]].y,mn[rs[k]].y);
44     mx[k].x=max(mx[ls[k]].x,mx[rs[k]].x);
45     mx[k].y=max(mx[ls[k]].y,mx[rs[k]].y);
46     if (ans[a[k].id])return;
47     mn[k].x=min(mn[k].x,a[k].a.x-a[k].r);
48     mn[k].y=min(mn[k].y,a[k].a.y-a[k].r);
49     mx[k].x=max(mx[k].x,a[k].a.x+a[k].r);
50     mx[k].y=max(mx[k].y,a[k].a.y+a[k].r);
51 
52 int build(int l,int r,int p)
53     if (l>r)return 0;
54     t=p;
55     nth_element(a+l,a+k,a+r+1);
56     ls[k]=build(l,k-1,p^1);
57     rs[k]=build(k+1,r,p^1);
58     up(l,r);
59     return k;
60  
61 void query(int l,int r,int x)
62     if (l>r)return;
63     if (calc(k,a[x].a)>sqr(a[x].r)+eps)return;
64     if ((!ans[a[k].id])&&(dis(a[x].a,a[k].a)<=sqr(a[x].r+a[k].r)+eps))ans[a[k].id]=a[x].id;
65     query(l,k-1,x);
66     query(k+1,r,x);
67     up(l,r);
68 
69 int main()
70     scanf("%d",&n);
71     for(int i=1;i<=n;i++)
72         scanf("%lf%lf%d",&a[i].a.x,&a[i].a.y,&a[i].r);
73         a[i].a=rotate(a[i].a);
74         a[i].id=id[i]=i;
75     
76     mn[0].x=mn[0].y=2e9+1;
77     mx[0].x=mx[0].y=-2e9-1;
78     build(1,n,0);
79     sort(id+1,id+n+1,cmp);
80     for(int i=1;i<=n;i++)
81         if (!ans[a[id[i]].id])query(1,n,id[i]);
82     for(int i=1;i<=n;i++)printf("%d ",ans[i]);
83 
View Code

 

 

以上是关于[loj2586]选圆圈的主要内容,如果未能解决你的问题,请参考以下文章

loj2538. 「PKUWC2018」Slay the Spire

loj2538. 「PKUWC2018」Slay the Spire

UITableviewCell - 在编辑模式下单击空复选标记圆圈不会选择单元格

loj6045 「雅礼集训 2017 Day8」价

将单选按钮中包含的小圆圈(点)的颜色更改为红色?

「APIO2018」选圆圈(K-D Tree/CDQ+Set)