由一些圆心都在x轴上的圆,任意两个圆的关系只会是内含,内切,外切,外离。求圆把平面分成多少个部分。
题目做法据说很多,仅知道其中两种:栈和并查集。
首先对圆进行排序,优先左端点位置,然后是半径长度。然后从左到右扫描一遍。
#include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <math.h> using namespace std; #define MAXN 300100 #define LL long long #define INF 1000000100 struct Circle { LL l, r, cnt, cap; Circle() {} Circle(LL _l, LL _r, LL _cnt, LL _cap): l(_l), r(_r), cnt(_cnt), cap(_cap){} bool operator <(const Circle &argu) const { if(l == argu.l) return argu.r < r; else return l < argu.l; } void out() { printf("%I64d %I64d %I64d %I64d\n", l, r, cnt, cap); } }cc[MAXN]; int n, ctop; LL x, r; int s[MAXN]; int main() { //freopen("1883.in", "r", stdin); scanf("%d", &n); cc[0] = Circle(-INF, (LL)2 * INF, (LL)1, (LL)3 * INF); for(int i = 1; i <= n; i++) { scanf("%I64d%I64d", &x, &r); cc[i] = Circle(x - r, x + r, (LL)1, (LL)2 * r); } n++; sort(cc, cc + n); ctop = s[0] = 0; for(int i = 1; i < n; i++) { while(cc[i].l >= cc[s[ctop]].r) { if(cc[s[ctop]].cap == 0) cc[s[ctop]].cnt++; cc[s[ctop - 1]].cnt += cc[s[ctop]].cnt; ctop--; } cc[s[ctop]].cap -= cc[i].r - cc[i].l; s[++ctop] = i; } while(ctop > 0) { if(cc[s[ctop]].cap == 0) cc[s[ctop]].cnt++; cc[s[ctop - 1]].cnt += cc[s[ctop]].cnt; ctop--; } printf("%I64d\n", cc[0].cnt); return 0; }