zoukankan      html  css  js  c++  java
  • 【loj2586】【APIO2018】选圆圈

    题目

    (n) 个圆$c_1,c_2, cdots , c_n $,执行如下的操作:

    找到剩下的半径最大的圆删除并删除所有和它有交的其他并没有被删除的圆;

    求每个圆是被那个圆删除的;

    $1 le n le 3 imes 10^5 $ ;

    描述

    • kdt做法:
      记录每个圆围成的举行作为剪枝,直接模拟删除;

      记得旋转一下,然后eps开1e-3就好;

    • 搬运一下$n log^2n $做法(orz yww):

      考虑找到和(c_i) 相交的半径最大的被自己删除的圆 ;

      这样的圆一定满足互相不相交;

      由于半径比 (c_i) 大,所以如果相交一定会和 (c_i) 平行坐标轴的四条切线有交;

      所以用扫描线+cdq分治即可;

      //懒得写正解了这是暴力:
      #include<bits/stdc++.h>
      #define eps 1e-3
      #define ld double
      using namespace std;
      const int N=300010;
      const ld sq2=sqrt(2);
      int n,WD,pos[N],bl[N],ls[N],rs[N],tr[N],rt;///
      struct P{ld x,y;};///
      ld mn[N][2],mx[N][2];///
      struct C{P o;ld r,mn[2],mx[2];int id;}c[N];///
      int dcmp(ld x){return fabs(x)<eps?0:x<0?-1:1;}///
      bool cmp(C A,C B){return !dcmp(A.r-B.r)?A.id<B.id:A.r>B.r;}///
      bool cmpD(int A,int B){return !WD?c[A].o.x<c[B].o.x:c[A].o.y<c[B].o.y;}///
      ld len(P A,P B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}///
      bool judge(C A,C B){return dcmp(len(A.o,B.o)-(A.r+B.r)*(A.r+B.r))<=0;}///
      void rotate(P&A){A=(P){(A.x-A.y)/sq2,(A.x+A.y)/sq2};}///
      char gc(){
      	static char*p1,*p2,s[1000000];
      	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      	return(p1==p2)?EOF:*p1++;
      }///
      int rd(){
      	int x=0,f=1;char C=gc();
      	while(C<'0'||C>'9'){if(C=='-')f=-1;C=gc();}
      	while(C>='0'&&C<='9'){x=x*10+C-'0';C=gc();}
      	return x*f;
      }///
      void build(int&k,int l,int r,int d){
      	WD=d;k=(l+r)>>1;
      	nth_element(tr+l,tr+k,tr+r+1,cmpD);
      	mn[k][0]=c[tr[k]].mn[0];
      	mx[k][0]=c[tr[k]].mx[0];
      	mn[k][1]=c[tr[k]].mn[1];
      	mx[k][1]=c[tr[k]].mx[1];
      	if(l<k){
      		build(ls[k],l,k-1,d^1);
      		for(int i=0;i<2;++i){
      			mn[k][i]=min(mn[k][i],mn[ls[k]][i]);
      			mx[k][i]=max(mx[k][i],mx[ls[k]][i]);
      		}
      	}
      	if(k<r){
      		build(rs[k],k+1,r,d^1);
      		for(int i=0;i<2;++i){
      			mn[k][i]=min(mn[k][i],mn[rs[k]][i]);
      			mx[k][i]=max(mx[k][i],mx[rs[k]][i]);
      		}
      	}
      }///
      bool jud(int x,int y){return !x||mx[x][0]<c[y].mn[0]-eps||mn[x][0]>c[y].mx[0]+eps||mx[x][1]<c[y].mn[1]-eps||mn[x][1]>c[y].mx[1]+eps;}///
      void query(int k,int x){
      	if(!bl[tr[k]]&&judge(c[tr[k]],c[x]))bl[tr[k]]=c[x].id;
      	if(!jud(ls[k],x))query(ls[k],x);
      	if(!jud(rs[k],x))query(rs[k],x);
      }///
      int main(){
      //	freopen("B.in","r",stdin);
      //	freopen("B.out","w",stdout);
      	n=rd();
      	for(int i=1;i<=n;++i){
      		c[i].o.x=rd();c[i].o.y=rd();
      		rotate(c[i].o);c[i].r=rd();
      		c[i].mn[0]=c[i].o.x-c[i].r;
      		c[i].mx[0]=c[i].o.x+c[i].r;
      		c[i].mn[1]=c[i].o.y-c[i].r;
      		c[i].mx[1]=c[i].o.y+c[i].r;
      		c[i].id=tr[i]=i;
      	}///
      	sort(c+1,c+n+1,cmp);
      	for(int i=1;i<=n;++i)pos[c[i].id]=i;
      	build(rt,1,n,0);
      	for(int i=1;i<=n;++i){
      		if(!bl[i])query(rt,i);
      	}
      	for(int i=1;i<=n;++i)printf("%d ",bl[pos[i]]);
      	return 0;//
      }//
      
  • 相关阅读:
    团队作业(三):确定分工
    团队作业(二):项目选题
    团队冲刺DAY3
    团队冲刺DAY4
    团队冲刺DAY6
    团队冲刺DAY1
    团队冲刺DAY5
    团队冲刺DAY7
    团队作业(四):描述设计
    【自学Spring Boot】什么是Spring Boot
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10794050.html
Copyright © 2011-2022 走看看