您的位置:首页 > 其它

HDU-2461 Rectangles 线段树,矩形面积并

2012-07-30 11:29 387 查看
首先申明此方法POJ超时,HDU压线过,优化版见/article/4949189.html

线段树的写法与上面链接中的离散化版本的想法是相近的,只不过这里仅仅是通过线段树来保留某一x区域的多个矩形的面积并。

代码如下:

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;

int N, M, Q, cnt;

map<int,int>mp;

struct Rectangle
{
int x1, y1, x2, y2;
}e[25];

struct High
{
int y;
bool operator < (High temp) const
{
return y < temp.y;
}
bool operator == (High temp) const
{
return y == temp.y;
}
}H[50];

struct xLine
{
int x, y1, y2, sign;
bool operator < (xLine temp) const
{
return x < temp.x;
}
}Line[50];

struct Node
{
int l, r, lazy;
}s[200];

void build(int p, int l, int r)
{
s[p].l = l, s[p].r = r;
s[p].lazy = 0;  // 初始化为被覆盖了0次
if (l != r) {
int mid = (l + r) >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
}

void push_up(int p)
{

}

void push_down(int p)
{
if (s[p].lazy != 0) {
s[p<<1].lazy += s[p].lazy;
s[p<<1|1].lazy += s[p].lazy;
s[p].lazy = 0;
}
}

void modify(int p, int l, int r, int val)
{
if (l == s[p].l && r == s[p].r) {
s[p].lazy += val;
}
else {
int mid = (s[p].l + s[p].r) >> 1;
push_down(p);
if (r <= mid) {
modify(p<<1, l, r, val);
}
else if (l > mid) {
modify(p<<1|1, l, r, val);
}
else {
modify(p<<1, l, mid, val);
modify(p<<1|1, mid+1, r, val);
}
push_up(p);
}
}

int query(int p)
{
if (s[p].l == s[p].r) {
return (bool)(s[p].lazy) * (H[s[p].r].y - H[s[p].l-1].y);
}
else {
push_down(p);
return query(p<<1) + query(p<<1|1);
}
}

int main()
{
int c, sum, ca = 0;
while (scanf("%d %d", &N, &M), N|M) {
for (int i = 1; i <= N; ++i) {
scanf("%d %d %d %d", &e[i].x1, &e[i].y1, &e[i].x2, &e[i].y2);
}
printf("Case %d:\n", ++ca);
for (int t = 1; t <= M; ++t) {
sum = 0;
mp.clear();
scanf("%d", &Q);
for (int j = 1, k = 0; j <= Q; ++j, k += 2) {
scanf("%d", &c);
Line[k].x = e[c].x1, Line[k+1].x = e[c].x2;
Line[k].sign = 1, Line[k+1].sign = -1;
// 定义 1为入边,-1为出边
Line[k].y1 = e[c].y1, Line[k].y2 = e[c].y2;
Line[k+1].y1 = e[c].y1, Line[k+1].y2 = e[c].y2;
H[k].y = e[c].y1, H[k+1].y = e[c].y2;
}
sort(H, H+2*Q); // 对y轴坐标进行离散话
cnt = unique(H, H+2*Q) - H; // 去重
for (int i = 0; i < cnt; ++i) {
mp[H[i].y] = i;
}
sort(Line, Line+2*Q);
for (int i = 0; i < 2*Q; ++i) {
Line[i].y1 = mp[Line[i].y1];
Line[i].y2 = mp[Line[i].y2];
// 将y坐标进行离散化
}
build(1, 0, cnt-1);  // 建立一个空的树来表示整个纵坐标的覆盖情况
modify(1, Line[0].y1+1, Line[0].y2, Line[0].sign);
for (int i = 1; i < (Q << 1); ++i) { // 遍历每一个
sum += query(1) * (Line[i].x - Line[i-1].x);
modify(1, Line[i].y1+1, Line[i].y2, Line[i].sign);
}
printf("Query %d: %d\n", t, sum);
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: