hdu1542矩形面积并

来源:互联网 发布:上海it外包公司 编辑:程序博客网 时间:2024/06/09 19:07

这个就是求矩形面积并,思考查阅了一晚上,终于会了这道题,好难,脑洞极大,不禁感叹kuangbin大神的能力,实在是太强了,真的,就用他的做模板,以后就不用什么对拍了。
这个题,这么回事,首先给离散化,把不相邻的点给变成1,2,3,4,5,6,按大小顺序来,还有就是,每一个矩形,加进来的时候,看cnt为多少,入边为1,出边为-1,这样的话,每一个矩形,就记住和y轴平行的边,记录,low和high,还有x,然后每次更新segTree【1】的cnt,最后就是用每一条线去乘,然后不断的加进来边。
我贴进来一个图,我是从左到右扫描的,他是从下到上扫描的,但是思想都是一样的。
不仅感叹,kuangbin实在是真的太厉害了,我感觉我可能不是很专心,状态不佳,加油!
这里写图片描述

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MaxN = 220;struct Node{    int l ,r ;//离散化后的节点左右点    int c;//覆盖了几次    double cnt;//离散化之后实际的值    double lf , rf;//节点的正确的左边和右边}segTree[MaxN * 4];struct Line{    double x , y1 , y2;//线的x,y1 = low y2 = high    int f;//1表入边,-1表出边}line[MaxN];bool cmp(Line a , Line b){    return a.x < b.x;}double y[MaxN];void Build(int i , int l , int r){    segTree[i].l = l;    segTree[i].r = r;    segTree[i].cnt = 0;    segTree[i].c = 0;    segTree[i].lf = y[l];//离散化的边    segTree[i].rf = y[r];    if(l + 1 == r) return;//由于是区间,所以线段树,这么排,例如10~15,15~20    int mid = (l + r) >> 1;    Build(i << 1 , l , mid);    Build(i << 1 | 1 , mid , r);}void calen(int i){    if(segTree[i].c > 0){//当为入边的时候就要+        segTree[i].cnt = segTree[i].rf - segTree[i].lf;        return;    }    if(segTree[i].l + 1 == segTree[i].r) segTree[i].cnt = 0;//当没有的时候,就不做了    else segTree[i].cnt = segTree[i << 1].cnt + segTree[i << 1 | 1].cnt;}void update(int i , Line e){    if(e.y1 == segTree[i].lf && e.y2 == segTree[i].rf){//加进来线恰好为节点的左右边时候        segTree[i].c += e.f;        calen(i);//更新一下节点的cnt        return;    }    if(e.y2 <= segTree[i << 1].rf) update(i << 1 ,e);    else if(e.y1 >= segTree[i << 1 | 1].lf) update(i << 1 | 1 ,e);    else{        Line tmp = e;        tmp.y2 = segTree[i << 1].rf;        update(i << 1 , tmp);        tmp = e;        tmp.y1 = segTree[i << 1 | 1].lf;        update(i << 1 | 1 , tmp);    }    calen(i);}int main(){    int cnt = 1;    double x1 , y1 , x2 , y2;    int n;    while(scanf("%d",&n),n){        int t = 1;        for(int i = 1 ; i <= n ; i++){            scanf("%lf %lf %lf %lf",&x1 , &y1 , &x2 , &y2);//离散化            line[t].x = x1;            line[t].y1 = y1;            line[t].y2 = y2;            line[t].f = 1;            y[t] = y1;            t++;            line[t].x = x2;            line[t].y1 = y1;            line[t].y2 = y2;            line[t].f = -1;            y[t] = y2;            t++;        }        sort(line + 1 , line + t , cmp);        sort(y + 1 , y + t);        Build(1 , 1 , t - 1);//建树        update(1 , line[1]);        double ans = 0;        for(int i = 2 ; i < t ; i++){            ans += segTree[1].cnt*(line[i].x - line[i - 1].x);            update(1 , line[i]);        }        printf("Test case #%d\nTotal explored area: %.2lf\n\n",cnt++,ans);    }    return 0;}

人一我百,人十我万,穷尽毕生,只为最强,不要输给wyy(前两句是kaungbin的,后两句是zqdnr的,最后一句是我的)

0 0