本代码采用的是横向扫描一遍和纵向扫描一遍来得到最终的结果,核心部分就是求举行周长并,当然也要对线段树比较熟悉才行,毕竟矩形周长并,面积并,面积交都要用到线段树来计算。说说求举行周长并的过程吧,我们先计算横向线段的长度,把所有坐标的y轴坐标按照升序排列,扫描线从y的最小值依次向上扫描,求出每次扫描所覆盖的长度,与上一次长度做差得到其绝对值(这个值不需要加到线段树中去),加到最终的答案中去。横向纵向都来一遍就得出最终的答案了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10020;
int n;
int all[2][maxn], tree[maxn << 2], lazy[maxn << 2];
struct rec
{
int l, r;
int order, val;
void setval(int a, int b, int c, int d)
{
l = a;
r = b;
order = c;
val = d;
}
friend bool operator < (rec a, rec b)
{
return a.order < b.order;
}
}a[2][maxn];
void update(int L, int R, int val, int l, int r, int rt, int flag)
{
if(l >= L && r <= R)
{
lazy[rt] += val;
if(lazy[rt])
tree[rt] = all[flag][r + 1] - all[flag][l];
else if(l == r)
tree[rt] = 0;
else
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
return ;
}
int m = (l + r) / 2;
if(m >= L)
update(L, R, val, l, m, rt << 1, flag);
if(m < R)
update(L, R, val, m + 1, r, rt << 1 | 1, flag);
if(lazy[rt])
tree[rt] = all[flag][r + 1] - all[flag][l];
else
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
int main()
{
//freopen("in.txt", "r", stdin);
cin >> n;
int m[4];
int x1, x2, y1, y2;
rec temp;
for(int i = 1; i <= n; ++ i)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
all[0][i] = x1, all[0][i + n] = x2;
all[1][i] = y1, all[1][i + n] = y2;
temp.setval(x1, x2, y1, 1);
a[0][i] = temp;
temp.setval(x1, x2, y2, -1);
a[0][i + n] = temp;
temp.setval(y1, y2, x1, 1);
a[1][i] = temp;
temp.setval(y1, y2, x2, -1);
a[1][i + n] = temp;
}
n <<= 1;
sort(all[0] + 1, all[0] + 1 + n);
m[0] = unique(all[0] + 1, all[0] + 1 + n) - all[0] - 1;
sort(all[1] + 1, all[1] + 1 + n);
m[1] = unique(all[1] + 1, all[1] + 1 + n) - all[1] - 1;
sort(a[0] + 1, a[0] + 1 + n);
sort(a[1] + 1, a[1] + 1 + n);
int ans = 0;
for(int i = 0; i <= 1; ++ i)
{
int last = 0;
memset(tree, 0, sizeof(tree));
memset(lazy, 0, sizeof(lazy));
for(int j = 1; j <= n; ++ j)
{
int l = lower_bound(all[i] + 1, all[i] + 1 + m[i], a[i][j].l) - all[i];
int r = lower_bound(all[i] + 1, all[i] + 1 + m[i], a[i][j].r) - all[i];
update(l, r - 1, a[i][j].val, 1, m[i], 1, i); ///范围是l到r-1,是因为线段树存的其实是点,要存区间的的话得稍加转换。
ans += abs(tree[1] - last);
last = tree[1];
}
}
cout << ans << endl;
return 0;
}