题目:
给n个矩形求周长并。
分析:
唯一需要注意的地方就是,对线段排序的时候不能单纯只考虑高度,还要考虑是上边还是下边。如果有一个上边和一个下边高度一样,那么应该让上边在前下边在后。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
#define lson rt*2,l,(l+r)/2
#define rson rt*2+1,(l+r)/2+1,r
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 1e5 + 5;
const int BASE = 10001;
struct Edge {
int x1, x2, y;
int f;
Edge () {}
Edge (int x1, int x2, int y, int f): x1(x1), x2(x2), y(y), f(f) {}
bool operator <(const Edge &edge) const {
if(y != edge.y) return y < edge.y;
return f < edge.f;
}
} e1[MAXN << 1], e2[MAXN << 1];
int n, cnt;
struct Seg_tree {
double tree[MAXN << 2];
int tag[MAXN << 2];
void build() {
ms(tree, 0); ms(tag, 0);
}
void pushup(int rt, int l, int r) {
if (tag[rt]) tree[rt] = r + 1 - l;
else if (l == r) tree[rt] = 0;
else tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void update(int L, int R, int rt, int l, int r, int t) {
if (L <= l && R >= r) {
tag[rt] += t;
pushup(rt, l, r);
return;
}
if (L <= (l + r) / 2) update(L, R, lson, t);
if (R > (l + r) / 2) update(L, R, rson, t);
pushup(rt, l, r);
}
} T;
int solve(Edge e[]) {
int ret = 0, last = 0;
for (int i = 1; i <= cnt; i++) {
T.update(e[i].x1, e[i].x2-1, 1, 1, 20000, e[i].f);
ret += abs(T.tree[1] - last);
last = T.tree[1];
}
return ret;
}
int main() {
// freopen("1.txt","r",stdin);
ios::sync_with_stdio(false);
while (cin >> n) {
int x1, x2, y1, y2;
cnt = 0;
for (int i = 0; i < n; i++) {
cin >> x1 >> y1 >> x2 >> y2;
e1[++cnt] = Edge(x1+BASE, x2+BASE, y1+BASE, -1);
e2[cnt] = Edge(y1+BASE,y2+BASE,x1+BASE,-1);
e1[++cnt] = Edge(x1+BASE, x2+BASE, y2+BASE, 1);
e2[cnt] = Edge(y1+BASE,y2+BASE,x2+BASE,1);
}
sort(e1 + 1, e1 + 1 + cnt);
sort(e2 + 1, e2 + 1 + cnt);
int ans = 0;
T.build();
ans += solve(e1);
T.build();
ans += solve(e2);
cout << ans << "\n";
}
return 0;
}