扫描线

题目链接

3068. 扫描线

3068. 扫描线(区间合并)

题目描述

在二维平面中给定 \(n\) 个两条边分别与 \(x\) 轴和 \(y\) 轴平行的矩形,请你求出它们的面积并。

输入格式

第一行包含整数 \(n\)

接下来 \(n\) 行,每行包含四个整数 \(x_1,y_1,x_2,y_2\),表示其中一个矩形的左下角坐标 \((x_1,y_1)\) 和右上角坐标 \((x_2,y_2\))。

注意,坐标轴 \(x\) 轴从左向右延伸,\(y\) 轴从下向上延伸。

image

输出格式

一个整数,表示矩形的面积并。

数据范围

\(1≤n≤1000\),
\(−10^9≤x_1<x_2≤10^9\),
\(−10^9≤y_1<y_2≤10^9\)

输入样例:

2
10 10 20 20
15 15 25 25

输出样例:

175

解题思路

先将所有的横坐标排序去重,再分别计算每两个横坐标之间的面积,面积即为两个横坐标的宽度乘上所有在两个横坐标之间有效的纵坐标的长度之和,即区间合并

  • 时间复杂度:\(O(n^2logn)\)

代码

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
using LL=long long;
const int N=1010;
pii l[N],r[N];
vector<int>xs; 
int n;
pii q[N];
LL cal(int a,int b)
{
    int cnt=0;
    for(int i=1;i<=n;i++)
        if(a>=l[i].fi&&b<=r[i].fi)q[cnt++]={l[i].se,r[i].se};
    if(!cnt)return 0;
    sort(q,q+cnt);
    LL res=0;
    int s=q[0].fi,e=q[0].se;
    for(int i=1;i<cnt;i++)
        if(q[i].fi<=e)e=max(e,q[i].se);
        else
        {
            res+=e-s;
            s=q[i].fi,e=q[i].se;
        }
    res+=e-s;
    return res*(b-a);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&l[i].fi,&l[i].se,&r[i].fi,&r[i].se);
        xs.push_back(l[i].fi);
        xs.push_back(r[i].fi);
    }
    sort(xs.begin(),xs.end());
    LL res=0;
    for(int i=0;i+1<xs.size();i++)
        if(xs[i]!=xs[i+1])
            res+=cal(xs[i],xs[i+1]);
    printf("%lld",res);
    return 0;
}
posted @ 2021-09-24 15:32  zyy2001  阅读(162)  评论(0编辑  收藏  举报