Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
The new general manager Gill Bates has been to a seminar on time management. Ever since she has been bothering all of her staff to manage their own time. Now she plans to take it one step further: she wants to start managing her space too. And since she has also learned to start small, she wants to start by managing her desk space. Work tends to pile up on her desk, especially since the time management training where she was taught to order all documents in neat piles and organize her work accordingly. She now needs to calculate how much desk space is occupied. For this she comes up with a cunning plan. First, she orders her staff to measure the size and exact location of each document on the desk, in tenths of millimeters accuracy. As Gill is a very tidy person, all her document are completely on her desk, and are all perfectly aligned to the edges of the desk (i.e. the edges of all documents are parallel to an edge of the desk). For each document, the staff writes down the position of the lower left corner of the document and its size.
What you need to do now is to write a program that, given the input from the staff, calculates the occupied space on the desk. The maximum size of the desk is 2 * 1 meters. There is a maximum of 500 documents on the desk.
Input
The first line of the input consists of the number N of desks to be considered. Next follows for each desk the number of documents. Then follows for each document a separate line with 4 numbers: the smallest X and Y co-ordinates (i.e. the lower left corner), and the width and height of the document respectively.
Output
The output consists of N lines containing the amount of occupied space on each desk in squared tenths of millimeters.
Sample Input
2 2 0 0 1000 1000 0 0 1000 1000 3 0 0 2 2 2 2 2 2 1 1 2 2
Sample Output
1000000 10
Solution
给定数个矩形的左下角和长宽,求这些矩形总共所占用的面积是多少,其中数据小于2000*1000。简单来说可以直接开数组,一个各格子用一个bool表示是否被占用,但是考虑双重循环,最大的运算量会是500*2000*1000,耗时太长。于是想到几天前接触到的一个离散化的方法,把已知的点投影的新的点上,做一个映射,根据已有的值重新排布坐标,再应用上述的bool矩阵表示是否被占用即可。注意对于映射之后,每一个格子的大小面积需要重新计算。
比如说原来是有两个点(0,0),(1000,1000),那么原来的坐标是x->(0,1,2,3,...,1000),映射之后就是(0,1000)只有两个点。预处理排序之后映射坐标,预处理每一个格子的面积,最后按点扫描,根据反馈结果累加求和即可。总体的复杂度就是点数的乘积。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
bool has[1005][1005], ending[1005]; //at most 1000 point
int toX[2005], toY[2005], s[1005][1005];
int px[1005], py[1005], ord[1005];
int cmpx(const int a, const int b) { return px[a] < px[b]; }
int cmpy(const int a, const int b) { return py[a] < py[b]; }
int main()
{
int n;
scanf("%d", &n);
while (n--)
{
int m, x0, y0, x1, y1;
memset(has, 0, sizeof has);
scanf("%d", &m);
for (int i = 0; i < m; ++i)
{
scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
x1 += x0;
y1 += y0;
px[i * 2] = x0; px[i * 2 + 1] = x1;
py[i * 2] = y0; py[i * 2 + 1] = y1;
ord[i * 2] = i * 2; ord[i * 2 + 1] = i * 2 + 1;
ending[i * 2 + 1] = i * 2;
}
sort(ord, ord + 2 * m, cmpx);
for (int i = 0; i < 2 * m; ++i) toX[i] = px[ord[i]], px[ord[i]] = i;
sort(ord, ord + 2 * m, cmpy);
for (int i = 0; i < 2 * m; ++i) toY[i] = py[ord[i]], py[ord[i]] = i;
for (int i = 0; i < 2 * m-1; ++i)
{
for (int j = 0; j < 2 * m-1; ++j)
{
s[i][j] = (toX[i + 1] - toX[i]) * (toY[j + 1] - toY[j]);
}
}
for (int p = 0; p < m; ++p)
{
int m = 2 * p;
for (int i = px[m]; i < px[m + 1]; ++i)
for (int j = py[m]; j < py[m + 1]; ++j) has[i][j] = true;
}
int ans = 0;
for (int i = 0; i < 1005; ++i)
for (int j = 0; j < 1005; ++j) if (has[i][j]) ans += s[i][j];
printf("%d\n", ans);
}
return 0;
}