• 【LOJ】#2586. 「APIO2018」选圆圈


    题解

    不旋转坐标系,TLE,旋转坐标系,最慢一个点0.5s……maya,出题人数据水平很高了……

    好吧,如果你不旋转坐标系,写一个正确性和复杂度未知的K - D树,没有优化,你可以得到87分的好成绩

    但是你就是傻逼,你就是写不出来,能有什么办法,APIO Ag滚粗了呗= =

    这道题看起来需要用什么东西维护一下平面,查找给定一个圆这个平面内多少个圆和它有交集,可以K - D树

    我们考虑维护一个集合里的圆覆盖的矩形,就是最大的横纵坐标和最小的横纵坐标,查询的时候只要看看和当前圆横纵坐标是不是有交集,有交集就查,同时维护一下这棵树里还有没有圆没有被删除
    当然复杂度可能会很劣……但是不劣的算法也不会,你就写了,写完之后87
    哦87挺好的哦,然而不是考场上我想写写100分啊,看了大家似乎旋转了坐标系,然后我也转了,咦我怎么WA了……把eps调小一点就过了

    为什么我那么菜啊= =

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <map>
    //#define ivorysi
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define mo 974711
    #define MAXN 300005
    #define eps 1e-3
    #define RG register
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {putchar('-');x = -x;}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct Point {
        db x,y;
        Point() {}
        Point(db _x,db _y) {
    	x = _x;y = _y;
        }
    };
    struct Circle {
        Point a;db R;int id;
    }cir[MAXN],C[MAXN];
    db o(db x) {
        return x * x;
    }
    db dist(Point a,Point b) {
        return o(a.x - b.x) + o(a.y - b.y);
    }
    bool cmpc(Circle s,Circle t) {
        return s.R > t.R || (s.R == t.R && s.id < t.id);
    }
    const db alpha = acos(-1.0) / 5;
    int tr[MAXN * 4],pos[MAXN],N,D[MAXN],tot,a[MAXN];
    bool vis[MAXN],dimension;
    struct node {
        Circle cir;Point r1,r2;
        node *lc,*rc;int siz;
        void update_siz() {
    	siz = 0;
    	if(!vis[cir.id]) siz = 1;
    	siz += lc->siz;
    	siz += rc->siz;
        }
        void update() {
    	r1.x = cir.a.x - cir.R;r1.y = cir.a.y - cir.R;
    	r2.x = cir.a.x + cir.R;r2.y = cir.a.y + cir.R;
    	r1.x = min(r1.x,min(lc->r1.x,rc->r1.x));
    	r1.y = min(r1.y,min(lc->r1.y,rc->r1.y));
    	r2.x = max(r2.x,max(lc->r2.x,rc->r2.x));
    	r2.y = max(r2.y,max(lc->r2.y,rc->r2.y));
        }
    }*rt,*null;
    
    bool cmp(Circle s,Circle t) {
        if(dimension) return s.a.x + s.R + eps < t.a.x + t.R;
        else return s.a.y + s.R + eps < t.a.y + t.R;
    }
    node* build(int l,int r,bool d) {
        if(l > r) return null;
        node *res = new node;
        int mid = (l + r) >> 1;
        dimension = d;
        nth_element(C + l,C + mid,C + r + 1,cmp);
        res->cir = C[mid];
        res->lc = build(l,mid - 1,d ^ 1);res->rc = build(mid + 1,r,d ^ 1);
        res->update();res->update_siz();
        return res;
    }
    bool fit(node *u,Circle S) {
        db l[2] = {u->r1.x,S.a.x - S.R};
        db r[2] = {u->r2.x,S.a.x + S.R};
        if(l[0] > l[1]) swap(l[0],l[1]),swap(r[0],r[1]);
        if(l[1] > r[0]) return 0;
        l[0] = u->r1.y,l[1] = S.a.y - S.R;
        r[0] = u->r2.y,r[1] = S.a.y + S.R;
        if(l[0] > l[1]) swap(l[0],l[1]),swap(r[0],r[1]);
        if(l[1] > r[0]) return 0;
        return 1;
    }
    void Query(node *u,Circle S) {
        if(!u->siz) return;
        if(!vis[u->cir.id]) {
    	if(dist(u->cir.a,S.a) <= o(u->cir.R + S.R) + eps) {
    	    vis[u->cir.id] = 1;
    	    a[u->cir.id] = S.id;
    	    --tot;
    	}
        }
        if(fit(u->lc,S)) Query(u->lc,S);
        if(fit(u->rc,S)) Query(u->rc,S);
        u->update_siz();
    }
    void Init() {
        null = new node;
        null->siz = 0;
        null->r1 = Point(2000000000,2000000000);
        null->r2 = Point(-2000000000,-2000000000);
        read(N);
        db x,y,r;
        for(int i = 1 ; i <= N ; ++i) {
    	scanf("%lf%lf%lf",&x,&y,&r);
    	cir[i] = (Circle){Point(x * cos(alpha) - y * sin(alpha),x * sin(alpha) + y * cos(alpha)),r,i};
    	C[i] = cir[i];
        }
        sort(cir + 1,cir + N + 1,cmpc);
        rt = build(1,N,0);
    }
    void Solve() {
        for(int i = 1 ; i <= N ; ++i) {
    	if(!a[cir[i].id]) Query(rt,cir[i]);
        }
        for(int i = 1 ; i <= N ; ++i) {
    	out(a[i]);if(i == N) enter;else space;
        }
        //out(clock());enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    
  • 相关阅读:
    java的System.getProperty()方法可以获取的值
    python-namedtuple使用
    ML-KDTree思想、划分、实现
    基于栈的10亿数字快速排序
    python栈、队列的使用
    1.(字符串)-计算n个数count-and-say
    1.(字符串)-获取最后一个字符串及长度
    1.(字符串)-空格替换
    1.(字符串)-获取字符串的最长回文子串
    1.(字符串)-回文判断
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9143572.html
Copyright © 2020-2023  润新知