【BZOJ 4561】【JLOI 2016】圆的异或并
2016-10-14 22:02
423 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=4561
一开始并不会做,后来看题解看懂了。
看懂了之后还是错了好几次,数组大小手残开小了。
圆的包含并不包括内切!
具体做法是扫描线, 维护扫描线中的圆和一个垂直于x轴的直线的交点,在扫描线中交点的纵坐标是递增的,每个圆和这条直线有两个交点。
遇到一个圆的左端点,查询它的upper_bound,如果upper_bound是一个圆的上半弧的交点,则它被这个圆包含;如果是一个圆的下半弧的交点,则它和这个圆被包含的状况相同。
然后把它的上半弧和下半弧加入扫描线,为了之后计算交点。
遇到一个圆的右端点,删除它的上半弧和下半弧。
圆只有相离和包含保证了扫描线的正确性。
扫描线可以用splay,set或fhqtreap维护,小神说总之是能查前驱后继的东东
今天终于会用set啦~~~
一开始并不会做,后来看题解看懂了。
看懂了之后还是错了好几次,数组大小手残开小了。
圆的包含并不包括内切!
具体做法是扫描线, 维护扫描线中的圆和一个垂直于x轴的直线的交点,在扫描线中交点的纵坐标是递增的,每个圆和这条直线有两个交点。
遇到一个圆的左端点,查询它的upper_bound,如果upper_bound是一个圆的上半弧的交点,则它被这个圆包含;如果是一个圆的下半弧的交点,则它和这个圆被包含的状况相同。
然后把它的上半弧和下半弧加入扫描线,为了之后计算交点。
遇到一个圆的右端点,删除它的上半弧和下半弧。
圆只有相离和包含保证了扫描线的正确性。
扫描线可以用splay,set或fhqtreap维护,小神说总之是能查前驱后继的东东
今天终于会用set啦~~~
#include<set> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 200003; int in() { int k = 0, fh = 1; char c = getchar(); for (; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for (; c >= '0' && c <= '9'; c = getchar()) k = k * 10 + c - 48; return k * fh; } struct Circle { int x, y, r; Circle(int _x = 0, int _y = 0, int _r = 0) : x(_x), y(_y), r(_r) {} } C ; struct Point { int id, x, mark; Point(int _id = 0, int _x = 0, int _mark = 0) : id(_id), x(_x), mark(_mark) {} bool operator < (const Point &A) const { return x < A.x; } } P[N << 1]; struct node { int id, mark; node(int _id = 0, int _mark = 0) : id(_id), mark(_mark) {} }; ll sqr(int x) {return 1ll * x * x;} int n, tot = 0, nowx, k ; set <node> S; set <node> :: iterator tmp; bool operator < (node A, node B) { double Y1 = (double) C[A.id].y + (double) A.mark * sqrt(sqr(C[A.id].r) - sqr(C[A.id].x - nowx)); double Y2 = (double) C[B.id].y + (double) B.mark * sqrt(sqr(C[B.id].r) - sqr(C[B.id].x - nowx)); return Y1 != Y2 ? Y1 < Y2 : A.mark < B.mark; } ll ans = 0; int main() { int x, y, r; n = in(); for (int i = 1; i <= n; ++i) { x = in(); y = in(); r = in(); C[i] = Circle(x, y, r); P[++tot] = Point(i, x - r, 1); P[++tot] = Point(i, x + r, -1); } sort(P + 1, P + tot + 1); for (int i = 1; i <= tot; ++i) { nowx = P[i].x; if (P[i].mark == 1) { tmp = S.upper_bound(node(P[i].id, 1)); if (tmp == S.end()) k[P[i].id] = 1; else if (tmp->mark == 1) k[P[i].id] = -k[tmp->id]; else k[P[i].id] = k[tmp->id]; S.insert(node(P[i].id, 1)); S.insert(node(P[i].id, -1)); } else { S.erase(node(P[i].id, 1)); S.erase(node(P[i].id, -1)); } } for(int i = 1; i <= n; ++i) ans += sqr(C[i].r) * k[i]; printf("%lld\n", ans); return 0; }
相关文章推荐
- BZOJ4561: [JLoi2016]圆的异或并 计算几何+treap
- 【BZOJ4561】[JLoi2016]圆的异或并 扫描线
- bzoj4561: [JLoi2016]圆的异或并 圆的扫描线
- [BZOJ4561][JLoi2016]圆的异或并(扫描线+splay)
- bzoj 4561: [JLoi2016]圆的异或并 (计算几何+扫描线+splay)
- BZOJ 4561 [JLoi2016]圆的异或并
- Bzoj4561 [JLoi2016]圆的异或并
- 【BZOJ 4561】【JLOI 2016】圆的异或并
- [扫描线 set] BZOJ 4561 [JLoi2016]圆的异或并
- 【bzoj4561】【JLOI2016】【圆的异或并】【扫描线+set】
- bzoj 4561: [JLoi2016]圆的异或并
- BZOJ 4561 [JLoi2016]圆的异或并 ——扫描线
- bzoj4561: [JLoi2016]圆的异或并
- 【BZOJ】4561: [JLoi2016]圆的异或并
- bzoj 4561: [JLoi2016]圆的异或并(扫描线+set)
- 4561 [JLoi2016] 圆的异或并
- bzoj4561【JZOI2016】圆的异或并
- 4561: [JLoi2016]圆的异或并
- bzoj 4557: [JLoi2016]侦察守卫
- [JLoi 2016] bzoj4559 成绩比较 [容斥原理]