zoukankan      html  css  js  c++  java
  • luogu P4631 [APIO2018] Circle selection 选圆圈

    传送门

    那个当前半径最大的圆可以用堆维护.这道题一个想法就是优化找和当前圆有交的圆的过程.考虑对于所有圆心建KD-tree,然后在树上遍历的找这样的点.只要某个点子树内的点构成的矩形区域到当前圆心的最近距离(>2)倍半径就不用找了

    然而在loj上过不去,这时就可以用一个很鸡贼的优化,对于所有点绕原点旋转一定角度,然后就跑的过了(可能是全在一条直线上建KD-tree会出锅(雾)).稍微注意精度误差就行了

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=3e5+10;
    const LL inf=1ll<<61;
    const db eps=1e-3,tpd=sqrt(2)/2;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int nd;
    struct point
    {
    	db d[2];
    	int i;
    	bool operator < (const point &bb) const {return fabs(d[nd]-bb.d[nd])>eps?d[nd]<bb.d[nd]:i<bb.i;}
    }a[N],b[N],qwq;
    struct cir
    {
    	point p;
    	db r;
    	bool operator < (const cir &bb) const {return fabs(r-bb.r)>eps?r<bb.r:p.i>bb.p.i;}
    }c[N];
    priority_queue<cir> hp;
    int n,m,rt,ch[N][2],an[N],ii;
    db mx[N][2],my[N][2];
    void bui(int &o,int l,int r,int nnd)
    {
    	if(l>r) return;
    	if(l==r)
    	{
    		o=b[l].i;
    		mx[o][0]=mx[o][1]=a[o].d[0];
    		my[o][0]=my[o][1]=a[o].d[1];
    		return;
    	}
    	int mid=(l+r)>>1;
    	nd=nnd;
    	nth_element(b+l,b+mid,b+r+1);
    	o=b[mid].i;
    	mx[o][0]=mx[o][1]=a[o].d[0];
    	my[o][0]=my[o][1]=a[o].d[1];
    	bui(ch[o][0],l,mid-1,nnd^1);
    	bui(ch[o][1],mid+1,r,nnd^1);
    	mx[o][0]=min(mx[o][0],min(mx[ch[o][0]][0],mx[ch[o][1]][0]));
    	mx[o][1]=max(mx[o][1],max(mx[ch[o][0]][1],mx[ch[o][1]][1]));
    	my[o][0]=min(my[o][0],min(my[ch[o][0]][0],my[ch[o][1]][0]));
    	my[o][1]=max(my[o][1],max(my[ch[o][0]][1],my[ch[o][1]][1]));
    }
    db dis(point aa,point bb){return (aa.d[0]-bb.d[0])*(aa.d[0]-bb.d[0])+(aa.d[1]-bb.d[1])*(aa.d[1]-bb.d[1]);}
    db expt(int o)
    {
    	if(!o) return inf;
    	db xx=min(mx[o][1]-qwq.d[0],qwq.d[0]-mx[o][0])<-eps?min(fabs(mx[o][1]-qwq.d[0]),fabs(qwq.d[0]-mx[o][0])):0;
    	db yy=min(my[o][1]-qwq.d[1],qwq.d[1]-my[o][0])<-eps?min(fabs(my[o][1]-qwq.d[1]),fabs(qwq.d[1]-my[o][0])):0;
    	return xx*xx+yy*yy;
    }
    void wk(int o)
    {
    	if(!o||expt(o)>(db)qwq.i*(db)qwq.i+eps) return;
    	if(!an[o])
    	{
    		db rr=(db)qwq.i/2+c[o].r;
    		if(dis(a[o],qwq)<rr*rr+eps) an[o]=ii;
    	}
    	wk(ch[o][0]),wk(ch[o][1]);
    }
    
    int main()
    {
    	n=rd();
    	for(int i=1;i<=n;++i)
    	{
    		db xx=rd(),yy=rd();
    		a[i].d[0]=tpd*xx+tpd*yy,a[i].d[1]=tpd*yy-tpd*xx;
    		a[i].i=i;
    		b[i]=a[i];
    		c[i].p=a[i],c[i].r=rd();
    		hp.push(c[i]);
    	}
    	mx[0][0]=my[0][0]=inf,mx[0][1]=my[0][1]=-inf;
    	bui(rt,1,n,0);
    	while("ji ni tai mei")
    	{
    		while(!hp.empty()&&an[hp.top().p.i]) hp.pop();
    		if(hp.empty()) break;
    		cir cc=hp.top();
    		hp.pop();
    		ii=cc.p.i;
    		qwq=cc.p,qwq.i=cc.r*2;
    		wk(rt);
    	}
    	for(int i=1;i<=n;++i) printf("%d ",an[i]);
        return 0;
    }
    
  • 相关阅读:
    [网鼎杯 2018]Comment-Git泄露部分
    Google Hacking 详解
    macOS修改Docker容器的端口映射配置
    CentOS6 7 8更换阿里yum源
    XSS代码合集(含测试效果详细版)-HTML4与更早版本的向量2
    VMware 启动Ubuntu时黑屏
    XSS代码合集(含测试效果详细版)-HTML4与更早版本的向量1
    APP安全在线检测网站
    Juice-Shop 二星题
    慕课网-安卓工程师初养成-4-5 练习题
  • 原文地址:https://www.cnblogs.com/smyjr/p/11054500.html
Copyright © 2011-2022 走看看