hdu1255 矩形面积二次交

来源:互联网 发布:windows 会员如何加入 编辑:程序博客网 时间:2024/05/17 03:52

http://acm.hdu.edu.cn/showproblem.php?pid=1255

理解hdu1542后,这题也就改一下就行了。

题意:给出n个矩形的左下角与右上角坐标,求矩形覆盖两次以上的面积

解题思路:

与hdu1542思路一样,将X坐标离散建树再一层一层计算面积,唯一不同在于这里多一个量twoMoreLen,向上更新时维护好twoMoreLen就好

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<iostream>#include<algorithm>#include<queue>#include<stack>#include<vector>#include<map>#include<set>#include<bitset>using namespace std;#define N 1100struct line{    double left,right,h;    int flag;}L[2*N];map<double,int>M;double X[2*N];double XLi[2*N];int cmp(line aa,line bb){    return aa.h<bb.h;}struct node{    int left,right,cover;//cover表示该段成段覆盖的次数,但不向下更新    double oneMoreLen,twoMoreLen;//该区间覆盖一次以上、两次以上的长度}seg_tree[N*4];void seg_built(int l,int r,int num){    seg_tree[num].left=l;    seg_tree[num].right=r;    seg_tree[num].cover=0;    seg_tree[num].oneMoreLen=0;    seg_tree[num].twoMoreLen=0;    if(r!=l+1)    {        int mid=(l+r)>>1;        seg_built(l,mid,num<<1);        seg_built(mid,r,num<<1|1);    }}void push_up(int num)//向上更新{    if(seg_tree[num].cover>=2)    {        seg_tree[num].twoMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];        seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];        return;    }    if(seg_tree[num].cover==1)    {        if(seg_tree[num].right==seg_tree[num].left+1)//叶子节点        {            seg_tree[num].twoMoreLen=0;            seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];        }        else//非叶子节点,twoMoreLen要看下面的oneMoreLen长度        {            seg_tree[num].twoMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;            seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];        }        return;    }    if(seg_tree[num].right==seg_tree[num].left+1)    {        seg_tree[num].oneMoreLen=0;        seg_tree[num].twoMoreLen=0;    }    else    {        seg_tree[num].oneMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;        seg_tree[num].twoMoreLen=seg_tree[2*num].twoMoreLen+seg_tree[2*num+1].twoMoreLen;    }}void seg_update(int l,int r,int value,int num){    if(l>=seg_tree[num].right||r<=seg_tree[num].left) return;    if(l<=seg_tree[num].left&&r>=seg_tree[num].right)    {        seg_tree[num].cover+=value;        push_up(num);        return;    }    seg_update(l,r,value,2*num);    seg_update(l,r,value,2*num+1);    push_up(num);}int main(){    int i,j,k;    int n,m,t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        M.clear();        m=0;        for(i=1;i<=n;i++)        {            double x1,x2,y1,y2;            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);            X[++m]=x1;            L[m].left=x1;            L[m].right=x2;            L[m].h=y1;            L[m].flag=1;//线段记录            X[++m]=x2;            L[m].left=x1;            L[m].right=x2;            L[m].h=y2;            L[m].flag=-1;//线段记录        }        sort(X+1,X+1+m);        sort(L+1,L+1+m,cmp);        M[X[1]]=1;        XLi[1]=X[1];        j=1;        for(i=2;i<=m;i++)//X坐标离散化        {            if(X[i]!=X[i-1])            {                M[X[i]]=++j;                XLi[j]=X[i];            }        }        seg_built(1,j,1);        double sum=0;        for(i=1;i<m;i++)        {            seg_update(M[L[i].left],M[L[i].right],L[i].flag,1);            sum+=seg_tree[1].twoMoreLen*(L[i+1].h-L[i].h);        }        printf("%.2lf\n",sum);    }}/*input:251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 0 2 12 0 3 1output:7.630.00*/

0 0