覆盖的面积 HDU - 1255 线段树+扫描线+离散化 求特定交叉面积

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
const int N=101010;
struct Node
{
    double x,yl,yh;
    int w;
    bool operator<(Node t)const
    {
        return x<t.x;
    }
    
}edge[N];
struct
{
    int l,r,cover;
}tr[N];
double ys[N];
void build(int u,int l,int r)
{
    int mid=l+r>>1;
    tr[u].l=l,tr[u].r=r;
    tr[u].cover=0;
    if (r-l>1)
    {
        build(u<<1,l,mid);
        build(u<<1|1,mid,r);
    }
}
void modify(int u,int l,int r,int val)
{
    int mid=tr[u].l+tr[u].r>>1;
    if(tr[u].l==l&&tr[u].r==r)
    {
        tr[u].cover+=val;
    }
    else if(tr[u].r-tr[u].l>1)
    {
        if (l>=mid)
            modify(u<<1|1,l,r,val);
        else if(r<=mid)
            modify(u<<1,l,r,val);
        else
        {
            modify(u<<1,l,mid,val);
            modify(u<<1|1,mid,r,val);
        }
    }
}
void query(int root,double &ans)
{
    //如果被覆盖次数大于1 
    if (tr[root].cover>1)
        ans+=ys[tr[root].r]-ys[tr[root].l];
    //上式不满足时,可能往下的子区间满足,就往下递归 
    //如果不是叶节点 
    else if(tr[root].r-tr[root].l>1)
    {
        tr[root<<1].cover+=tr[root].cover;
        tr[root<<1|1].cover+=tr[root].cover;
        tr[root].cover=0; 
        query(root<<1,ans);
        query(root<<1|1,ans);
    }
}
int main()
{
    int T,N;
    double x1,x2,y1,y2,ans,res;
    scanf("%d",&T);
    while(T--)
    {
        res=0;
        map<double,int>mp;
        scanf("%d",&N);
        for (int i=1,j=1;i<=N;++i,j+=2)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            //入边 
            edge[j].x=x1,edge[j].yl=y1,edge[j].yh=y2;
            edge[j].w=1;
            //出边 
            edge[j+1].x=x2,edge[j+1].yl=y1,edge[j+1].yh=y2;
            edge[j+1].w=-1;
            //扫描线 
            ys[j]=y1,ys[j+1]=y2;

        }
        //按x排序 
        sort(edge+1,edge+1+2*N);
        //y离散化 
        sort(ys+1,ys+1+2*N);
        int cnt=unique(ys+1,ys+1+2*N)-(ys+1);
        build(1,1,cnt);
        //离散化 
        //映射之后的编号 ,查询的实话再映射到ys中去 
        for (int i=1;i<=cnt;++i)
            mp[ys[i]]=i;
        for (int i=1;i<2*N;++i)
        {
            ans=0;
            //插进去 
            modify(1,mp[edge[i].yl],mp[edge[i].yh],edge[i].w);
            query(1,ans);
            res+=ans*(edge[i+1].x-edge[i].x);
        }
        printf("%.2lf\n",res);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/QingyuYYYYY/p/12296805.html