O - 覆盖的面积 - hdu 1255(求面积)

分析:求一层的面积覆盖是非常简单的事情,不过多层面积覆盖应该怎么搞???也是比较简单的事情,只需要用两个变量记录就好了,一个记录覆盖一次的,一个记录覆盖两次的,就很容易解决了

************************************************************************
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std; #define Lson r<<1
#define Rson r<<1|1 const int MAXN = 1e5+; struct segmentTree
{///cover 记录区间被覆盖了多少次
    int L, R, cover;
    double len1, len2;///分别记录被覆盖一次和多次时候的长度
    int mid(){return (L+R)>>;}
}a[MAXN<<];
///保存离散化后的数据,nh是数组大小
double Hash[MAXN]; int nh; ///dir等于 1 是y的左边, -1是y的右边
struct Point{double x, y1, y2; int dir;}ege[MAXN];
bool cmp(Point n1, Point n2)
{///按照x从小到大排序
    return n1.x < n2.x;
}
double FindSegLen(int y1, int y2)
{///查找线段的长度, y1 < y2
    return Hash[y2] - Hash[y1];
}
void BuildTree(int r, int L, int R)
{
    a[r].L = L, a[r].R = R, a[r].cover = ;
    a[r].len1 = a[r].len2 = ;     if(L == R-)return ;     BuildTree(Lson, L, a[r].mid());
    BuildTree(Rson, a[r].mid(), R);
}
void PushUp(int r)
{
    if(a[r].cover > )
        a[r].len1 = a[r].len2 = FindSegLen(a[r].L, a[r].R);
    else if(a[r].L == a[r].R- && a[r].cover == )
        a[r].len1 = FindSegLen(a[r].L, a[r].R), a[r].len2 = ;
    else if(a[r].L == a[r].R-)
        a[r].len1 = a[r].len2 = ;
    else if(a[r].cover == )
    {///不是叶子节点点,覆盖两次以上的就等于子树覆盖一次的
        a[r].len2 = a[Lson].len1 + a[Rson].len1;
        a[r].len1 = FindSegLen(a[r].L, a[r].R);
    }
    else
    {///区间未被覆盖过,只能等于子树被覆盖的情况
        a[r].len1 = a[Lson].len1 + a[Rson].len1;
        a[r].len2 = a[Lson].len2 + a[Rson].len2;
    }
}
void UpData(int r, int L, int R, int dir)
{///注意叶子节点的合并操作
    if(a[r].L == L && a[r].R == R)
    {
        a[r].cover += dir;
        PushUp(r);         return ;
    }     if(R <= a[r].mid())
        UpData(Lson, L, R, dir);
    else if(L >= a[r].mid())
        UpData(Rson, L, R, dir);
    else
    {
        UpData(Lson, L, a[r].mid(), dir);
        UpData(Rson, a[r].mid(), R, dir);
    }     PushUp(r);
} int main()
{
    int i, T, N;     scanf("%d", &T);     while(T--)
    {
        double x1, x2, y1, y2, area=; int k=; nh = ;         scanf("%d", &N);         for(i=; i<N; i++)
        {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            ege[k].x=x1, ege[k].y1=y1, ege[k].y2=y2, ege[k++].dir=;///左边
            ege[k].x=x2, ege[k].y1=y1, ege[k].y2=y2, ege[k++].dir=-;///右边
            Hash[nh++] = y1, Hash[nh++] = y2;
        }         sort(Hash, Hash+nh);///排序并且去重复
        nh = unique(Hash, Hash+nh) - Hash;         ///建立以1区间为单位的线段树
        BuildTree(, , nh-);         ///对y边按照x从小到大排序
        sort(ege, ege+k, cmp);         for(int i=; i<k-; i++)
        {
            int L = lower_bound(Hash, Hash+nh, ege[i].y1)-Hash;
            int R = lower_bound(Hash, Hash+nh, ege[i].y2)-Hash;             UpData(, L, R, ege[i].dir);;             area += a[].len2 * (ege[i+].x - ege[i].x);
        }         printf("%.2f\n", area);
    }     return ;
}
上一篇:nginx源码分析--使用GDB调试(strace、 pstack )


下一篇:机器学习:Python中如何使用最小二乘法