扫描线
想法挺妙 搞了很长很长时间。。。
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; }