代码备份:动态维护半平面交/凸包

来源:互联网 发布:淘宝怎么查订单号物流 编辑:程序博客网 时间: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;}

原创粉丝点击