题目链接:[ HDU - 1828 ]
题目大意:给你n个矩形的左下角坐标和右上角坐标,求外周长。
题解
扫描线 + 离散化板子
将横竖两次扫描简化
代码如下
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10010;
const int maxN = 80010;
const int INF = 0x3f3f3f3f;
inline int read(void)
{
int w = 1, d = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
d = d * 10 + ch - '0';
ch = getchar();
}
return w * d;
}
struct Node {
int l, r, cnt;
int lc, rc;
int len, num;
} tree[maxN];
struct node {
int x1, x2, y, flag;
void init(int l, int r, int h, int f) {
x1 = l, x2 = r, y = h, flag = f;
}
bool operator < (const node& a) {
return y < a.y;
}
} line[maxn];
int n, x1, y11, x2, y2;
void build_tree(int id, int l, int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].cnt = 0;
tree[id].len = 0;
tree[id].lc = 0;
tree[id].rc = 0;
tree[id].num = 0;
if (l == r)
return;
int mid = (l + r) >> 1;
build_tree(id << 1, l, mid);
build_tree(id << 1 | 1, mid + 1, r);
}
void getlen(int i)
{
if (tree[i].cnt) {
tree[i].len = tree[i].r - tree[i].l + 1;
tree[i].lc = tree[i].rc = 1;
tree[i].num = 1;
}else if (tree[i].l == tree[i].r) {
tree[i].len = 0;
tree[i].lc = tree[i].rc = 0;
tree[i].num = 0;
} else {
tree[i].len = tree[i << 1].len + tree[i << 1 | 1].len;
tree[i].lc = tree[i << 1].lc;
tree[i].rc = tree[i << 1 | 1].rc;
tree[i].num = tree[i << 1].num + tree[i << 1 | 1].num - (tree[i << 1].rc & tree[i << 1 | 1].lc);
}
}
void update(int id, int l, int r, int v)
{
if (tree[id].l == l && tree[id].r == r) {
tree[id].cnt += v;
getlen(id);
return;
}
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid)
update(id << 1, l, r, v);
else if (l > mid)
update(id << 1 | 1, l, r, v);
else {
update(id << 1, l, mid, v);
update(id << 1 | 1, mid + 1, r, v);
}
getlen(id);
}
int main(void)
{
ios::sync_with_stdio(false);
while (~scanf("%d", &n)) {
int minn = INF, maxx = -INF;
for (int i = 0; i < n; i++) {
x1 = read(), y11 = read(), x2 = read(), y2 = read();
maxx = max(maxx, max(x1, x2));
minn = min(minn, min(x1, x2));
line[i].init(x1, x2, y11, 1);
line[i + n].init(x1, x2, y2, -1);
}
sort(line, line + 2 * n);
build_tree(1, minn, maxx - 1);
long long ans = 0, last = 0;
for (int i = 0; i < 2 * n; i++) {
update(1, line[i].x1, line[i].x2 - 1, line[i].flag);
ans += abs(tree[1].len - last);
ans += (line[i + 1].y - line[i].y) * tree[1].num * 2;
last = tree[1].len;
}
cout << ans << endl;
}
return 0;
}