zoukankan      html  css  js  c++  java
  • [BZOJ5465][APIO2018]选圆圈(KD-Tree)

    题意:给你n个圆,每次选择半径最大的,将它和与它相交的圆全部删去,输出每个圆是在哪次被删的。

    KD树模板题。用一个矩形框住这个圆,就可以直接剪枝了。为了防止被卡可以将点旋转一个角度,为了保险还可以多转几个角度。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 typedef double db;
     6 using namespace std;
     7 
     8 const int N=300010;
     9 const db inf=1e20,eps=1e-3,alpha=acos(-1)/3;
    10 int n,rt,ans[N];
    11 db x,y,r;
    12 struct P{ db x,y,r; int id; }cur,a[N];
    13 struct Tr{ int ls,rs; db x1,y1,x2,y2; P c; }T[N];
    14 
    15 bool cmpx(const P &a,const P &b){ return a.x<b.x; }
    16 bool cmpy(const P &a,const P &b){ return a.y<b.y; }
    17 bool cmpr(const P &a,const P &b){ return (a.r==b.r) ? a.id<b.id : a.r>b.r; }
    18 
    19 void F(int x,int y){
    20     T[x].x1=min(T[x].x1,T[y].x1); T[x].x2=max(T[x].x2,T[y].x2);
    21     T[x].y1=min(T[x].y1,T[y].y1); T[x].y2=max(T[x].y2,T[y].y2);
    22 }
    23 
    24 void upd(int x){
    25     if (ans[T[x].c.id]) T[x].x1=T[x].y1=inf,T[x].x2=T[x].y2=-inf;
    26     else{
    27         T[x].x1=T[x].c.x-T[x].c.r; T[x].x2=T[x].c.x+T[x].c.r;
    28         T[x].y1=T[x].c.y-T[x].c.r; T[x].y2=T[x].c.y+T[x].c.r;
    29     }
    30     if (T[x].ls) F(x,T[x].ls);
    31     if (T[x].rs) F(x,T[x].rs);
    32 }
    33 
    34 int build(int l,int r,int k){
    35     if (l>r) return 0;
    36     int mid=(l+r)>>1; nth_element(a+l,a+mid,a+r+1,k?cmpy:cmpx);
    37     T[mid].c=a[mid];
    38     T[mid].ls=build(l,mid-1,k^1); T[mid].rs=build(mid+1,r,k^1);
    39     upd(mid); return mid;
    40 }
    41 
    42 db sqr(db x){ return x*x; }
    43 bool Out(int x){ return (T[x].x2<cur.x-cur.r-eps) || (T[x].x1>cur.x+cur.r+eps) || (T[x].y2<cur.y-cur.r-eps) || (T[x].y1>cur.y+cur.r+eps); }
    44 bool chk(P &a){ return sqr(a.x-cur.x)+sqr(a.y-cur.y)<=sqr(a.r+cur.r)+eps; }
    45 
    46 void que(int x){
    47     if (Out(x)) return;
    48     if (!ans[T[x].c.id] && chk(T[x].c)) ans[T[x].c.id]=cur.id;
    49     if (T[x].ls) que(T[x].ls);
    50     if (T[x].rs) que(T[x].rs);
    51 }
    52 
    53 int main(){
    54     freopen("apiob.in","r",stdin);
    55     freopen("apiob.out","w",stdout);
    56     scanf("%d",&n);
    57     rep(i,1,n)
    58         scanf("%lf%lf%lf",&x,&y,&r),a[i]=(P){x*cos(alpha)+y*sin(alpha),y*cos(alpha)-x*sin(alpha),r,i};
    59     rt=build(1,n,0); sort(a+1,a+n+1,cmpr);
    60     rep(i,1,n) if (!ans[a[i].id]) ans[a[i].id]=a[i].id,cur=a[i],que(rt);
    61     rep(i,1,n) printf("%d ",ans[i]); puts("");
    62     return 0;
    63 }
  • 相关阅读:
    Hibernate3 第一天
    Struts2第四天
    Struts2第二天
    Struts2第一天
    【剑指offer】数字在排序数组中出现的次数,C++实现
    【剑指offer】两个链表的第一个公共结点,C++实现
    【剑指offer】数组中的逆序对。C++实现
    [Python]定时任务框架 APScheduler
    [pandas] SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
    alicode35-找出二叉搜索树的第2大的数
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9162178.html
Copyright © 2011-2022 走看看