bzoj4561

扫描线

想法挺妙 搞了很长很长时间。。。

http://www.cppblog.com/superlong/archive/2010/08/06/122427.html

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> PII;
const int N = 400010;
int n;
ll ans, nowx;
int x[N], y[N], r[N], mark[N]; 
inline ll sqr(int x)
{
    return (ll)x * (ll)x;
} 
struct data {
    int id, w;
    data(int id = 0, int w = 0) : id(id), w(w) {}    
    bool friend operator < (data A, data B)
    {
        double l1 = (double)y[A.id] + (double)A.w * sqrt(sqr(r[A.id]) - sqr(nowx - x[A.id]));
        double l2 = (double)y[B.id] + (double)B.w * sqrt(sqr(r[B.id]) - sqr(nowx - x[B.id]));
        return l1 == l2 ? A.w < B.w : l1 < l2;            
    }
};
vector<PII> v;
set<data> s;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d%d%d", &x[i], &y[i], &r[i]);
        v.push_back(make_pair((ll)x[i] - (ll)r[i], i));
        v.push_back(make_pair((ll)x[i] + (ll)r[i], -i));
    }
    sort(v.begin(), v.end());
    for(int i = 0; i < v.size(); ++i)
    {
        PII t = v[i];
        int p = t.second;
        nowx = v[i].first;
        if(p < 0)
        {
            s.erase(data(-p, -1));
            s.erase(data(-p, 1));    
        }
        else
        {                    
            set<data> :: iterator it = s.upper_bound(data(p, 1));
            if(it == s.end()) 
                mark[p] = 1;
            else if(it -> w == 1)
                mark[p] = -mark[it -> id];
            else mark[p] = mark[it -> id];
            s.insert(data(p, -1));
            s.insert(data(p, 1));
        }
    }
    for(int i = 1; i <= n; ++i)
        ans += (ll)mark[i] * (ll)r[i] * (ll)r[i];
    printf("%lld\n", ans);
    return 0;
}
View Code

 

posted @ 2017-07-18 18:38  19992147  阅读(147)  评论(0编辑  收藏  举报