代码备份:动态维护半平面交/凸包
来源:互联网 发布:淘宝怎么查订单号物流 编辑:程序博客网 时间:2024/06/04 23:58
以前写的代码,怕以后找不到了,放在这里安全点。
其实没太多的技术含量,用平衡树维护,配合链表,利用增量算法的思想,注意细节,使劲写就行了。
动态维护半平面交
# include <cstdlib># include <cstdio># include <cmath># include <cstring>using namespace std;const int maxn = 100000+ 20;const double eps = 1e-6;double sx, sy;int prev[maxn], next[maxn];double a[maxn];int n, tot, root, aux[maxn], link[maxn][2];struct line{double a, b, c, k;void reverse(){a = -a, b = -b, c = -c;}}lin[maxn];struct point {double x, y, z;}lp[maxn], rp[maxn];inline bool bezero(double x){return x < eps && x > -eps ? true: false;}inline bool stayout(line u, point v){return u.a*v.x + u.b*v.y + u.c*v.z < -eps ? true:false;}point get_point(line u, line v){point g;g.x = u.b*v.c - u.c*v.b;g.y = u.c*v.a - u.a*v.c;g.z = u.a*v.b - u.b*v.a;if (!bezero(g.z)) g.x /= g.z, g.y /= g.z, g.z = 1;return g;}inline double cross(point u, point v){return u.x*v.y - u.y*v.x;}void updata(int i){a[i] = a[link[i][0]] + a[link[i][1]] + cross(lp[i], rp[i]);}void rotate(int &i, int p){int j = link[i][p];link[i][p] =link[j][!p];link[j][!p] = i;updata(i);updata(j);i = j;}void insert(int &i, int x){if (i == 0) i = x, aux[i] = rand() << 10 + rand();else{int p = (lin[x].k > lin[i].k-eps);insert(link[i][p], x);if (aux[i] < aux[link[i][p]]) rotate(i, p); } }void cancel(int &i, int x){if (i == x)if (link[i][0] && link[i][1]){int p = aux[link[i][1]] > aux[link[i][0]];rotate(i, p);cancel(link[i][!p], x);} else i = link[i][link[i][1]!= 0];else cancel(link[i][lin[x].k > lin[i].k-eps], x);}void updata(int i, int j){ if (i != j) {if (lin[j].k-lin[i].k <-eps ) updata(link[i][0], j);else updata(link[i][1], j);}updata(i);}void findpred(int i, int x, int &l){if (!i) return ;if (lin[x].k > lin[i].k-eps) l = i, findpred(link[i][1], x, l);else findpred(link[i][0], x, l);}int findlast(int i){return link[i][1] == 0? i: findlast(link[i][1]);}void remove(int x){prev[next[x]] = prev[x];next[prev[x]] = next[x];}void make_line(double x1, double y1, double x2, double y2){tot++; double z1 = 1,z2 = 1;lin[tot].a = y1*z2 - y2*z1; lin[tot].b = z1*x2 - z2*x1;lin[tot].c = x1*y2 - x2*y1;lin[tot].k = atan2(x2-x1, y1-y2);point g = (point){x1+y1-y2, y1+x2-x1,1};if (stayout(lin[tot], g)) lin[tot].reverse();}void prepare(){int i;lin[1] = (line){0,-1,sy, atan2(-1,0)};lin[2] = (line){1,0,0, atan2(0,1)};lin[3] = (line){0,1,0, atan2(1,0)};lin[4] = (line){-1,0,sx,atan2(0,-1)};prev[1] = 4; next[1] = 2; prev[2] = 1; next[2] = 3;prev[3] = 2; next[3] = 4; prev[4] = 3; next[4] = 1;for (i =1; i <= 4; i++) { lp[i] = get_point(lin[i], lin[prev[i]]), rp[i] = get_point(lin[i], lin[next[i]]);insert(root, i); updata(root, i); } tot = 4;}int main(){int i; double x1, y1, x2, y2;int l, r;freopen("h.in", "r", stdin);freopen("h.out", "w", stdout);scanf("%d%lf%lf", &n, &sx, &sy);prepare();for (i = 1; i <= n; i++){scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);make_line(x1, y1, x2, y2);l = 0;findpred(root, tot, l);if (l == 0) l = findlast(root);r = next[l];if ( stayout(lin[tot], lp[r])){ for (;stayout(lin[tot], lp[l]);) cancel(root, l), remove(l), l = prev[l]; for (;stayout(lin[tot], rp[r]);) cancel(root, r), remove(r), r = next[r]; insert(root, tot); lp[tot] = get_point(lin[tot], lin[l]); rp[tot] = get_point(lin[tot], lin[r]); rp[l] = lp[tot]; lp[r] =rp[tot]; next[l] = tot; prev[tot] = l; next[tot] = r; prev[r] = tot; updata(root, tot); updata(root, l); updata(root, r); }printf("%.4lf\n", a[root]*0.5);}return 0;}
动态维护凸包:
include <cstdlib># include <cstdio># include <cstring># include <cmath># include <ctime>using namespace std;const double eps = 1e-6;const int maxn = 200000;int link[maxn][2], prev[maxn], next[maxn], te[maxn], aux[maxn];long long area[maxn], ans;int butler, root, tot, n;struct point {long long x, y;double k;void read(){scanf("%I64d%I64d", &x, &y);x*= 3; y*= 3;}void make(point base){long long dx = x - base.x, dy = y - base.y;k = atan2(dy, dx)*1e3;}}base,d[maxn];long long cross(int u, int v){return 1LL* d[u].x*d[v].y-1LL*d[u].y*d[v].x;}long long cross2(int a, int b, int c, int e){long long x1=d[b].x-d[a].x, y1=d[b].y-d[a].y, x2=d[e].x-d[c].x, y2=d[e].y-d[c].y;return 1LL*x1*y2 - 1LL*x2*y1;}void rotate(int &i, int p){int j = link[i][p];link[i][p] = link[j][!p];link[j][!p] = i; i = j;}void insert(int &i, int x){int p;if (i == 0) te[i = ++butler] = x, aux[i] = rand()<<15+rand();else{if (d[x].k - d[te[i]].k < -eps) p = 0; else p = 1;insert(link[i][p], x);if (aux[i] < aux[link[i][p]]) rotate(i, p); }}void prepare(){int i, j; point tmp;d[1].read(); d[2].read(); d[3].read(); base.x = (d[1].x+d[2].x+d[3].x)/3;base.y = (d[1].y+d[2].y+d[3].y)/3;d[1].make(base); d[2].make(base); d[3].make(base);for (i = 1; i <= 3; i++) for (j = i+1; j <= 3; j++) if (d[i].k > d[j].k) tmp = d[i], d[i] = d[j], d[j] = tmp;prev[1] = 3; next[1] = 2; area[1] = cross(3, 1); insert(root, 1);prev[2] = 1; next[2] = 3; area[2] = cross(1, 2); insert(root, 2);prev[3] = 2; next[3] = 1; area[3] = cross(2, 3); insert(root, 3);ans = area[1] + area[2] + area[3]; tot = 3;}void findpred(int i, int j, int &l){if (!i) return;if (d[te[i]].k - d[j].k > -eps) return findpred(link[i][0], j, l);else l = te[i], findpred(link[i][1], j, l);}int findlast(int i){if (link[i][1] == 0) return te[i]; else return findlast(link[i][1]);}void cancel(int &i, int c){if (!i) return;if (te[i] == c){if (link[i][0] && link[i][1]){int p = aux[link[i][1]] > aux[link[1][0]];rotate(i, p);cancel(link[i][!p], c);}else i = link[i][link[i][1]!= 0];}else{int p = d[c].k - d[te[i]].k > eps;cancel(link[i][p], c);}}void remove(int x){next[prev[x]] = next[x];prev[next[x]] = prev[x];}int main(){int i, l, r;freopen("convex.in", "r", stdin);freopen("convex.out", "w", stdout);prepare();scanf("%d", &n);for (i = 1; i <= n; i++){d[++tot].read(); l = 0; d[tot].make(base);findpred(root, tot, l); if (l == 0) l = findlast(root);r = next[l];if (cross2(l, tot, l, r) >= 0){ for (;cross2(tot, prev[l], tot, l) <= 0; ) cancel(root, l), ans -= area[l], remove(l),l = prev[l]; for (;cross2(tot, next[r], tot, r) >= 0; ) cancel(root, r), ans -= area[r], remove(r),r = next[r]; prev[tot] = l; next[tot] = r; next[l] = tot; prev[r] = tot; ans += (area[tot] = cross(l, tot)); long long g = area[r]; ans += ((area[r] = cross(tot, r)) - g); insert(root, tot); } printf("%I64d\n", abs(ans)/9);} return 0;}
- 代码备份:动态维护半平面交/凸包
- POJ 3384 Feng Shui 凸包直径 + 半平面交
- HDU 4316 凸包 +半平面交
- 大白 计算几何专题 凸包、半平面交、平面区域 部分例题练习题总结
- 动态维护凸包
- [半平面交对偶凸包] BZOJ 1007 [HNOI2008]水平可见直线
- [凸包最大内接圆 二分 半平面交] POJ 3525 Most Distant Point from the Sea
- pku2451 半平面交
- 半平面交
- 半平面交
- poj2540 半平面交
- 半平面交
- poj2451 半平面交
- 半平面交.....
- 半平面交
- POJ3384+半平面交
- HDU1632+半平面交
- POJ3525+半平面交
- win7+fedora16启动项问题
- ehCache+spring的简单实用
- android开发者网站
- makefile
- Sizes of iPhone UI Elements
- 代码备份:动态维护半平面交/凸包
- 任务管理--杀进程
- 面试题:strcpy、strchr、strstr的实现
- Android 调式:Re-installation failed due to different application signatures.
- F0/1,F0/2.....F0/24,F1/1,F1/2....F1/24含义
- android开发实例02:列表字母索引与过滤检索
- 餐馆那些事之:Proxy Pattern
- 苹果下的建模
- 热门:响应图片(Responsive Images)技术简介