线段树 蓝桥 油漆问题 求相交长方形面积

X星球的一批考古机器人正在一片废墟上考古。

该区域的地面坚硬如石、平整如镜。

管理人员为方便,建立了标准的直角坐标系。

每个机器人都各有特长、身怀绝技。

它们感兴趣的内容也不相同。

经过各种测量,每个机器人都会报告一个或多个矩形区域,作为优先考古的区域。

矩形的表示格式为 (x1,y1,x2,y2)

,代表矩形的两个对角点坐标。

为了醒目,总部要求对所有机器人选中的矩形区域涂黄色油漆。

小明并不需要当油漆工,只是他需要计算一下,一共要耗费多少油漆。

其实这也不难,只要算出所有矩形覆盖的区域一共有多大面积就可以了。

注意,各个矩形间可能重叠。
输入格式

第一行,一个整数 n

,表示有多少个矩形。

接下来的 n
行,每行有 4 个整数 x1,y1,x2,y2

,空格分开,表示矩形的两个对角顶点坐标。
输出格式

一行一个整数,表示矩形覆盖的总面积。
数据范围

1≤n≤10000
,
0≤x1,x2,y2,y2≤10000
数据保证 x1<x2 且 y1<y2


输入样例1:

3
1 5 10 10
3 1 20 20
2 7 15 17

输出样例1:

340

输入样例2:

3
5 2 10 6
2 7 12 10
8 1 15 15

输出样例2:

128

这种方法叫做扫描线线段树法。讲矩形的竖直距离转化为线段树,用cnt表示区间被覆盖的数量,len表示至少被覆盖的长度,那么根节点的len就是矩形的宽,按照横坐标排序,横坐标之差乘以根节点的len就是一段区间的矩形面积。

#include<bits/stdc++.h>
using namespace std;
const   int N=10010;
struct node
{
    int x;
    int y1;
    int y2;
    int k;
    bool operator <(const node&w)const
    {
        return x<w.x;
    }
}triangle[N*2];
struct nn
{
    int l;
    int r;
    int cnt;
    int len;
}tr[N*4];
void pushup(int u)
{
    if(tr[u].cnt>0) tr[u].len=tr[u].r-tr[u].l+1;
    else    if(tr[u].l==tr[u].r)    tr[u].len=0;
    else    tr[u].len=tr[u<<1].len+tr[u<<1|1].len;
}
void build(int u,int l,int r)
{
    tr[u]={l,r};
    if(l==r)    return;
    int mid= l+r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u);
}
void modify(int u,int l,int r,int k)
{
    if(tr[u].l>=l&&tr[u].r<=r)
    {
        tr[u].cnt+=k;
        pushup(u);
    }
    else
    {
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)   modify(u<<1,l,r,k);
        if(r>mid)   modify(u<<1|1,l,r,k);
        pushup(u);
    }
}
int main()
{
    int n;
    cin>>n;
    int m=0;
    for(int i=1;i<=n;i++)
    {
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        triangle[m++]={x1,y1,y2,1};//1代表已经覆盖
        triangle[m++]={x2,y1,y2,-1};//-1代表还没覆盖
    }
    sort(triangle,triangle+m);
    build(1,0,10000);//从0开始到最大y的值
    int res=0;
    for(int i=0;i<m;i++)
    {
        if(i>0)    res+=(triangle[i].x-triangle[i-1].x)*tr[1].len;
        modify(1,triangle[i].y1,triangle[i].y2-1,triangle[i].k); //n个区间有n+1个点,所以要减1。    
    }
    printf("%d\n",res);
    return 0;
}
发布了165 篇原创文章 · 获赞 8 · 访问量 2498

猜你喜欢

转载自blog.csdn.net/qq_45961321/article/details/104743274
今日推荐