• 【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;//
      }//
      
  • 相关阅读:
    tomcat拒绝接收请求记录
    js阻止事件冒泡
    BZOJ 5381 or & Codeforces 623E Transforming Sequence DP+NTT
    BZOJ5384 有趣的字符串题 回文树
    Codeforces 932G Palindrome Partition 回文树+DP
    LOJ2542 随机游走 Min-Max容斥+树上期望DP
    LOJ6070 基因 分块+回文自动机
    BZOJ3682 Phorni 后缀平衡树
    Codeforces 994F Compute Power 二分+DP
    BZOJ2759一个动态树好题 LCT
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10794050.html
Copyright © 2020-2023  润新知