倪文迪陪你学蓝桥杯2021寒假每日一题:1.12日(2017省赛A第10题)

2021年寒假每日一题,2017~2019年的省赛真题。
本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供。

后面的每日一题,每题发一个新博文,请大家看博客目录https://blog.csdn.net/weixin_43914593
@

2017省赛A类第10题,最后一题,题目链接:
油漆面积 http://oj.ecustacm.cn/problem.php?id=1324

1、题目描述


平面上有n个矩形,给出每个矩形的坐标。这些矩形可能有重叠。
问这些矩形覆盖的总面积是多少。
数据规模:1<=n<10000,坐标0<= x1,y1,x2,y2 <=10000
资源约定:内存 < 256M;CPU < 2000ms


2、题解

  本题是一个经典问题:“矩形面积并”。
  首先给出两种暴力法。
  (1)先单独求每个矩形的面积,然后把所有矩形的面积加起来,最后减去任意两个矩形的交集。求矩形的交集很花时间,需要两两配对,复杂度(O(n^2))
  (2)另一种更简单的暴力法,是把平面划成单位边长为1(面积也是1)的方格。每读入一个矩形,就把它覆盖的方格标注为已覆盖;对所有矩形都这样处理,最后统计被覆盖的方格数量即可。编码极其简单,但是比上一种方法更慢,且消耗极大的空间。
  本题的数据非常弱:矩形数量少,坐标值也不大。用第(2)种暴力法,也能通过。对,就这么干!

3、暴力

#include<bits/stdc++.h>
using namespace std;
bool vis[10001][10001];   //100M内存

int main(){
    int n,sum=0;   //sum:面积
    scanf("%d",&n);
    for(int k=0;k<n;k++){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);  //读一个矩形
        if(x1>x2)  swap(x1,x2);    //坐标排序
        if(y1>y2)  swap(y1,y2);
        for(int i=x1;i<x2;i++)     //统计这个矩形覆盖的面积
            for(int j=y1;j<y2;j++)
                if(!vis[i][j]){    //没有被覆盖过
                    sum++;         //统计面积
                    vis[i][j]=1;   //标注为已经覆盖
                }
    }
    cout<<sum;
    return 0;
}

3、标准解法

  当n很大,n<100000,且坐标值很大时,暴力法显然会超时。
  “矩形面积并”的标准解法是线段树的扫描线,建模和编码可不容易。参考博文“线段树”:
  https://blog.csdn.net/weixin_43914593/article/details/108221534
  其中的“7.1 矩形面积并”,和本题完全相同。

原文地址:https://www.cnblogs.com/luoyj/p/14271432.html