POJ 2932 Coneology (平面扫描)

题目:传送门

题意: 给你 n 个不相交的圆, 问你有多少圆不被其他圆内含。

解: 我们把所有圆的左端点和右端点的 x 单独拿出来按升序排序, 然后从左往右扫。

   然后遇到左边点就判断这个圆是否被内含, 不被内含就加入 ans。 

     具体可看代码。

  

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std;

const int N = 4e4 + 5;

double x[N], y[N], r[N];

vector < pair< double, int > > Q;
set < pair < double, int > > S;
vector < int > ans;

bool judge(int i, int j) { /// 题目保证了两两圆之间互不相交,那两圆只能是外相离, 或者内相离,内相离也就是内含
    return ((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])) <= r[j] * r[j];
}

int main() {

    int n; scanf("%d", &n);
    rep(i, 0, n - 1) {
        scanf("%lf %lf %lf", &r[i], &x[i], &y[i]);
        Q.pb(make(x[i] - r[i], i)); Q.pb(make(x[i] + r[i], i + n));
    }
    sort(Q.begin(), Q.end());
    for(int i = 0; i < Q.size(); i++) {
        int id = Q[i].second;
        if(id < n) { /// 左端点
            set < pair < double, int > >::iterator it = S.lower_bound(make(y[id], id)); /// 找到第一个比当前点的纵坐标大的点
            if(it != S.end() && judge(id, it->second)) continue; 
            if(it != S.begin() && judge(id, (--it)->second)) continue;
            ans.pb(id); S.insert(make(y[id], id));
        }
        else S.erase(make(y[id - n], id - n));
    }
    sort(ans.begin(), ans.end());
    printf("%d
", (int)ans.size());
    for(int i = 0; i < ans.size(); i++) printf("%d ", ans[i] + 1);
    return 0;
}
一步一步,永不停息
原文地址:https://www.cnblogs.com/Willems/p/12341001.html