hdu1542 Atlantis

来源:互联网 发布:无法连接到emule网络 编辑:程序博客网 时间:2024/05/22 03:52

求矩形面积的并,这个题应该是线段树刚刚出现在竞赛时要做的题。

这个题的主要思想就是扫描,我们将所有矩形竖直方向的两条线段,都拿出来排序,然后扫描用线段树维护覆盖的线段长度即可。


对于如上的矩形给所有竖直线段排序后就可以得到下面的图


我们可以观察到从一条线段到下一条线段之前竖直方向的覆盖长度a都不变,而这两条线段之间的距离为b,那么这两条线段之间的面积表示为a * b。

邻近的两条竖直的线段将整个图形分解成若干个部分,我们按上面的方法计算的面积的和就是面积的并了。

为了快速得到竖直方向的覆盖情况,我们用线段树来维护。

比如上图,第一条线段覆盖了a1,到下一条线段的距离为b1,计算面积;第二条与第一条线段共同覆盖了a2,到下一条线段的距离为b2;第三条线段退出覆盖,覆盖的长度为a3(a3==a1),到下一线段的距离为b3....

那么总面积为a1 * b1 + a2 * b2 + a3 * b3 ...

就可以输出答案了。

代码很丑,慢慢看。

#include<cstdio>#include<algorithm>using namespace std;struct node {    double x, y;};struct edge {    double x;    int st, ed;    int wt;    bool operator < (const edge &rhs)   const   {        return x < rhs.x;    }};const int MAXN = 500;int n;node A[MAXN + 10], B[MAXN + 10];int nn;edge Edge[MAXN + 10];int mx;double val[MAXN + 10];struct seg  {    int l, r;    int sig;    double cnt;    inline double length()  {   return val[r] - val[l]; }    void update(seg &lch, seg &rch)   {        if(sig) cnt = length();        else {            if(l + 1 >= r)  cnt = 0;            else cnt = lch.cnt + rch.cnt;        }    }}   Tree[MAXN * 4 + 10];void Build(int u, int l, int r)    {    seg &cur = Tree[u];    cur.l = l, cur.r = r;    cur.cnt = cur.sig = 0;    if(l + 1 >= r)  return ;    int mid = (l + r) / 2;    Build(u * 2, l, mid);    Build(u * 2 + 1, mid, r);}void Ins(int u, int l, int r, int x)  {    seg &cur = Tree[u], &lch = Tree[u * 2], &rch = Tree[u * 2 + 1];    if(cur.l >= r || cur.r <= l)    return ;    else if(l <= cur.l && cur.r <= r)   cur.sig += x;    else {        Ins(u * 2, l, r, x);        Ins(u * 2 + 1, l, r, x);    }    cur.update(lch, rch);}double work()   {    mx = nn = 0;    for(int i = 1; i <= n; i++) val[++mx] = A[i].y, val[++mx] = B[i].y;    sort(val + 1, val + 1 + mx);    mx = unique(val + 1, val + 1 + mx) - val - 1;    for(int i = 1; i <= n; i++) {        int y1 = lower_bound(val + 1, val + 1 + mx, A[i].y) - val, y2 = lower_bound(val + 1, val + 1 + mx, B[i].y) - val;        Edge[++nn] = (edge){A[i].x, y1, y2, 1};        Edge[++nn] = (edge){B[i].x, y1, y2, -1};    }    sort(Edge + 1, Edge + 1 + nn);    double ans = 0;    double Last = 0;    Build(1, 1, mx);    for(int i = 1; i <= nn; i++)    {        if(i != 1)  ans += Tree[1].cnt * (Edge[i].x - Last);        Last = Edge[i].x;        Ins(1, Edge[i].st, Edge[i].ed, Edge[i].wt);    }    return ans;}int main()  {    int kase = 0;    while(scanf("%d", &n) == 1 && n)    {        for(int i = 1; i <= n; i++) {            scanf("%lf%lf", &A[i].x, &A[i].y);            scanf("%lf%lf", &B[i].x, &B[i].y);        }        printf("Test case #%d\nTotal explored area: %.2f\n\n", ++kase, work());    }    return 0;}

相应的我们也会求矩形面积的交、并、以及周长了。

poj1177 求轮廓周长

hdu1255 求面积的交

hdu4419 也可以算求矩形面积的交吧

hdu4052 可以转化模型为求矩形面积的并


0 0
原创粉丝点击