http://train.usaco.org/usacoprob2?a=NaWWtjt80VA&S=rect1
题目大意:在一个A*B的坐标区域内(A,B <= 10000)从底向上覆盖N(N <= 1000)个不同颜色(用数字表示1~2500)的矩形,求最后能够被看到的颜色和他们各自覆盖的面积(桌布底色为1,需要考虑)
很直观的就把他和之前一道矩形覆盖的题目联系了起来,用一个链表(数组)按次序存储然后对每一矩形先算面积,再上浮并分裂计算其被覆盖的面积,原本以为会RE,毕竟我用的是递归计算,在计算底层是得要递归N次,但没想到竟然通过了,真是难以置信,那这么看来这道题比之前那道反而简单,因为他连移动都不需要所以直接用数组就行
看了官方题解之后发现其实可以改成在插入每一个矩形时将下方矩形分裂,这样就不会有RE的风险,而且虽然在最坏情况下每一次分裂都会产生三个新矩形(4-1),但是新产生的四个小矩形再下次分裂时不可能再各自产生四个(最多就总共多产生四个)。不过这样一来就要用链表存储矩形,遍历链表的时候也要注意下一个要跳过刚刚新分裂出的矩形
/*
ID: frontie1
TASK: rect1
LANG: C++
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int INFI = 0x3f3f3f3f;
struct rectangle
{
int upp;
int dow;
int lef;
int rig;
int color;
rectangle(int u = INFI, int d = 0, int l = 0, int r = INFI, int c = 0):upp(u), dow(d), lef(l), rig(r), color(c){};
int overlap(const rectangle &obj)
{
int u = min(upp, obj.upp);
int d = max(dow, obj.dow);
int l = max(lef, obj.lef);
int r = min(rig, obj.rig);
if(u <= d || r <= l) return 0;
else return ((u-d) * (r-l));
}
int area()
{
return ((upp-dow) * (rig-lef));
}
};
int N;
rectangle arr[1010];
int area[2505];
int covered(rectangle obj, int num)
{
if(num > N) return 0;
rectangle tar = arr[num];
int output = obj.overlap(tar);
if(output == 0) output += covered(obj, num+1);
else{
rectangle tem;
if(tar.lef > obj.lef) output += covered(rectangle(obj.upp, obj.dow, obj.lef, tar.lef, obj.color), num+1);
if(tar.rig < obj.rig) output += covered(rectangle(obj.upp, obj.dow, tar.rig, obj.rig, obj.color), num+1);
if(tar.upp < obj.upp) output += covered(rectangle(obj.upp, tar.upp, max(tar.lef, obj.lef), min(tar.rig, obj.rig), obj.color), num+1);
if(tar.dow > obj.dow) output += covered(rectangle(tar.dow, obj.dow, max(tar.lef, obj.lef), min(tar.rig, obj.rig), obj.color), num+1);
}
return output;
}
int main()
{
freopen("rect1.in", "r", stdin);
freopen("rect1.out", "w", stdout);
cin >> arr[0].rig >> arr[0].upp;
arr[0].color = 1;
cin >> N;
for(int i = 1; i <= N; ++i){
cin >> arr[i].lef >> arr[i].dow >> arr[i].rig >> arr[i].upp >> arr[i].color;
}
for(int i = 0; i <= N; ++i){
area[arr[i].color] += arr[i].area();
area[arr[i].color] -= covered(arr[i], i+1);
}
for(int i = 1; i <= 2500; ++i){
if(area[i] != 0) cout << i << ' ' << area[i] << endl;;
}
return 0;
}