題目鏈接
題意
給出n個矩形,求面積并。
思路
使用掃描線,我這里離散化y軸,按照x坐標從左往右掃過去。離散化后的y軸可以用線段樹維護整個y上面的線段總長度,當碰到掃描線的時候,就可以統計面積。這里要注意線段樹上結點維護的是線段的信息,而不是點的信息。
參考資料
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
#define lson l, m, rt<<1
#define rson m + 1, r, rt<<1|1
struct Node {int st;double l, r, id;bool operator < (const Node &rhs) const {return id < rhs.id;}
} p[N];
double y[N], tree[N<<2];
int cnt[N<<2];void PushUp(int l, int r, int rt) {if(cnt[rt] > 0) tree[rt] = y[r+1] - y[l]; // r + 1是因為線段樹上結點是線段,映射成點就要+1else if(l == r) tree[rt] = 0; // 當這個線段沒有cnt的時候就代表消失了else tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}void Update(int L, int R, int w, int l, int r, int rt) {if(L <= l && r <= R) {cnt[rt] += w;PushUp(l, r, rt);return ;}int m = (l + r) >> 1;if(L <= m) Update(L, R, w, lson);if(m < R) Update(L, R, w, rson);PushUp(l, r, rt);
}int main() {int cas = 1, n;while(scanf("%d", &n), n) {int cnt = 0, m = 0;for(int i = 1; i <= n; i++) {double x1, x2, y1, y2;scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);y[++cnt] = y1, y[++cnt] = y2;p[++m] = (Node) { 1, y1, y2, x1 };p[++m] = (Node) { -1, y1, y2, x2 };}sort(y + 1, y + 1 + cnt);sort(p + 1, p + 1 + m);cnt = unique(y + 1, y + 1 + cnt) - y - 1;double ans = 0;for(int i = 1; i <= m; i++) {ans += tree[1] * (p[i].id - p[i-1].id);int L = lower_bound(y + 1, y + 1 + cnt, p[i].l) - y;int R = lower_bound(y + 1, y + 1 + cnt, p[i].r) - y - 1;// R - 1是因為線段樹上的結點是線段Update(L, R, p[i].st, 1, cnt, 1);printf("%d : %d - %d , %.2f\n", i, L, R, tree[1]);}printf("Test case #%d\n", cas++);printf("Total explored area: %.2f\n\n", ans);}return 0;
}
轉載于:https://www.cnblogs.com/fightfordream/p/7591674.html
總結
以上是生活随笔為你收集整理的HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。