• 洛谷P4631/uoj415/loj2586 [APIO2018] Circle selection 选圆圈


    考虑和一个圆有交集的圆,是平面上的一块区域,所以我们考虑用 (KDtree) 维护。

    两个圆相交的条件 (displaystyle (X_i-X_j)^2+(Y_i-Y_j)^2 leqslant (R_i+R_j)^2)

    考虑怎么剪枝,直接维护 (X,Y,R) 的话不好维护。我们知道圆 (i) 和圆 (j) 有交集的话肯定会和框住圆 (j) 的最小的正方形有交集。

    所以我们维护 (KDtree) 一个子树里所有圆对应的正方形 (X,Y) 的最值来剪枝即可。

    (yuan) 里的 (l,r) :对应的正方形的左下角和右上角的坐标。

    (shu) 里的 (l,r) :子树里正方形 (x,y) 坐标的最小值和最大值。

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #define int long long
    #define lson tr[k].ls
    #define rson tr[k].rs
    using namespace std;
    int n, nowk, cnt, root;
    const int N = 300010;
    int s[N], ans[N];
    struct dian {int x, y;};
    struct yuan {int x, y, R, id; dian l, r;} cir[N];
    struct shu {int ls, rs, id; dian l, r;} tr[N];
    int my1(yuan a, yuan b) {return a.R == b.R ? a.id<b.id: a.R>b.R;}
    int my2(int a, int b) {return nowk ? cir[a].x < cir[b].x : cir[a].y < cir[b].y;}
    void pushup(int k)
    {
    	tr[k].l = cir[tr[k].id].l; tr[k].r = cir[tr[k].id].r;
    	if (lson)tr[k].l.x = min(tr[k].l.x, tr[lson].l.x), tr[k].l.y = min(tr[k].l.y, tr[lson].l.y), tr[k].r.x = max(tr[k].r.x, tr[lson].r.x), tr[k].r.y = max(tr[k].r.y, tr[lson].r.y);
    	if (rson)tr[k].l.x = min(tr[k].l.x, tr[rson].l.x), tr[k].l.y = min(tr[k].l.y, tr[rson].l.y), tr[k].r.x = max(tr[k].r.x, tr[rson].r.x), tr[k].r.y = max(tr[k].r.y, tr[rson].r.y);
    }
    void build(int &k, int l, int r, int now)
    {
    	if (l > r)return;
    	int mid = (l + r) >> 1;
    	nowk = now; nth_element(s + l, s + mid, s + r + 1, my2);
    	k = ++cnt; tr[k].id = s[mid];
    	build(lson, l, mid - 1, now ^ 1); build(rson, mid + 1, r, now ^ 1);
    	pushup(k);
    }
    int p2(int x) {return x * x;}
    int jiao(int i, int j) {return p2(cir[i].x - cir[j].x) + p2(cir[i].y - cir[j].y) <= p2(cir[i].R + cir[j].R);}
    void change(int k, int id)
    {
    	if (!k)return;
    	if (cir[id].r.x < tr[k].l.x || tr[k].r.x < cir[id].l.x || cir[id].r.y < tr[k].l.y || tr[k].r.y < cir[id].l.y)return;
    	if (!ans[cir[tr[k].id].id] && jiao(tr[k].id, id))ans[cir[tr[k].id].id] = cir[id].id;
    	if (lson)change(lson, id); if (rson)change(rson, id);
    }
    signed main()
    {
    	cin >> n;
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%lld%lld%lld", &cir[i].x, &cir[i].y, &cir[i].R);
    		cir[i].l.x = cir[i].x - cir[i].R; cir[i].l.y = cir[i].y - cir[i].R; cir[i].r.x = cir[i].x + cir[i].R; cir[i].r.y = cir[i].y + cir[i].R;
    		cir[i].id = i; s[i] = i;
    	}
    	sort(cir + 1, cir + 1 + n, my1); build(root, 1, n, 0);
    	for (int i = 1; i <= n; ++i)
    		if (!ans[cir[i].id])change(root, i);
    	for (int i = 1; i <= n; ++i)printf("%lld ", ans[i]);
    	return 0;
    }
    

    然而 (uoj)(loj) 上有 (hack) 数据,我们只要充分发挥人类智慧旋转一下坐标系就行了。记得开 (long space double).代码在这

  • 相关阅读:
    数据结构的入门
    Google 插件
    树莓派的第一次
    MySQL下载与安装
    SVN图标不显示问题
    excel 批量生成SQL语句
    版本管理工具
    RSA加密、解密、签名、验签的原理及方法
    获取客户端内网IP
    eclipse 添加svn插件
  • 原文地址:https://www.cnblogs.com/wljss/p/12627526.html
Copyright © 2020-2023  润新知