http://codeforces.com/gym/101147/problem/I
对于每一个圆。可以算出一个区间[L, R]使得半径为m的圆在这个区间里,一定能包含它。
然后就是区间减法问题里。用map存一下就好
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> int n, m; const double eps = 1e-10; bool flag; double calcLeft(LL x, LL y, LL r) { double t = m - r; double res = t * t - y * y; if (res < 0) { flag = false; return eps; } return x - sqrt(res); } double calcRight(LL x, LL y, LL r) { double t = m - r; double res = t * t - y * y; // assert(res >= 0); return x + sqrt(res); } map<double, LL>mp; void work() { mp.clear(); scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { int x, y, r; scanf("%d%d%d", &x, &y, &r); if (r > m) continue; flag = true; double res = calcLeft(x, y, r); if (flag) { mp[res] += r; mp[calcRight(x, y, r) + eps] -= r; } } if (mp.size() == 0) { printf("0 "); return; } map<double, LL> :: iterator it1 = mp.begin(); LL ans = it1->second; LL pre = it1->second; it1++; for (it1; it1 != mp.end(); it1++) { pre += it1->second; ans = max(ans, pre); } printf("%I64d ", ans); } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif freopen("walk.in", "r", stdin); int t; scanf("%d", &t); while (t--) work(); return 0; }