hdu1255 覆盖的面积(线段树+离散化+扫描线)

来源:互联网 发布:天刀怎样下载捏脸数据 编辑:程序博客网 时间:2024/06/05 15:35

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

题目:可以参考hdu1542 http://blog.csdn.net/qq_36782366/article/details/75209119

思路:用sum数组记录重叠两次以上的边的长度  once数组记录重叠一次边的记录  方便于信息的向上传递

其他的与hdu1542一致,这里主要讲下这两个数组的使用

关于pushup函数的解释(重点)

void PushUp(int rt,int l,int r) {if (cnt[rt]>=2){sum[rt] = X[r+1] - X[l];//需要理解once[rt]=0;return;} if(cnt[rt]==1){sum[rt] = once[rt<<1]+once[rt<<1|1]+sum[rt<<1]+sum[rt<<1|1];once[rt]=X[r+1] - X[l]-sum[rt];return ;} if(cnt[rt]==0){sum[rt] = sum[rt<<1] + sum[rt<<1|1];once[rt]=once[rt<<1]+once[rt<<1|1];return ;}}

如果cntr【rt】等于2时,说明该区间被该区间长度的边覆盖了两层,所以对于sum(两层以上的的长度)就是该区间的长度,因为已经覆盖两层了,所以once长度即为0

如果cnt【rt】等于1时,说明该区间被该区间长度的边覆盖了一层,所以对于sum(两层以上的的长度)就是其子区间中覆盖一层和两层以上的长度和,对于once一层的长度为总的该区间长度减去两层以上的长度

如果cnt【rt】等于0时,说明该区间没有被该区间长度的边覆盖,所以对于sum(两层以上的的长度)就是其子区间中覆盖两层以上的长度和,对于once一层的长度即等于其子区间中覆盖一层的长度和


好了接下来直接上AC的代码

#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>using namespace std;#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn = 22022;int cnt[maxn << 2];double sum[maxn << 2];double once[maxn<<2];double X[maxn];struct Seg{    double h , l , r;    int s;    Seg(){}    Seg(double a,double b,double c,int d) : l(a) , r(b) , h(c) , s(d) {}    bool operator < (const Seg &cmp) const    {         if( h==cmp.h)return s>cmp.s;        return h < cmp.h;    }}ss[maxn];void PushUp(int rt,int l,int r) {    if (cnt[rt]>=2)    {        sum[rt] = X[r+1] - X[l];//需要理解        once[rt]=0;        return;    }     if(cnt[rt]==1)    {        sum[rt] = once[rt<<1]+once[rt<<1|1]+sum[rt<<1]+sum[rt<<1|1];        once[rt]=X[r+1] - X[l]-sum[rt];        return ;    }     if(cnt[rt]==0)    {        sum[rt] = sum[rt<<1] + sum[rt<<1|1];        once[rt]=once[rt<<1]+once[rt<<1|1];        return ;    }}void update(int L,int R,int c,int l,int r,int rt){    if (L <= l && r <= R)    {        cnt[rt] += c;//这个位置的边的条数  如果大于0时需要计入底边        PushUp(rt , l , r);        return ;    }    int m = (l + r) >> 1;    if (L <= m)        update(L , R , c , lson);    if (m < R)        update(L , R , c , rson);    PushUp(rt , l , r);}int main(){    int n , cas;    scanf("%d",&cas);    while (cas--)    {        scanf("%d",&n) ;        int m = 0;        while (n --)        {            double a , b , c , d;            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);            X[m] = a;            ss[m++] = Seg(a , c , b , 1);            X[m] = c;            ss[m++] = Seg(a , c , d , -1);        }        sort(X , X + m);        sort(ss , ss + m);         int k=unique(X,X+m)-X;        memset(cnt , 0 , sizeof(cnt));        memset(sum , 0 , sizeof(sum));        memset(once, 0 , sizeof(once));        double ret = 0;        for (int i = 0 ; i < m - 1 ; i ++)        {            int l=lower_bound(X,X+k,ss[i].l)-X;            int r =lower_bound(X,X+k,ss[i].r)-X-1;            if (l <= r) update(l , r , ss[i].s , 0 , k - 1, 1);//扫描线段时更新底边长度和底边相差个数                ret += sum[1] * (ss[i+1].h - ss[i].h);//底乘以高        }        printf("%.2lf\n", ret);    }    return 0;}