覆蓋的面積Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4304 Accepted Submission(s): 2139
Problem Description給定平面上若干矩形,求出被這些矩形覆蓋過至少兩次的地區的面積.
Input輸入資料的第一行是一個正整數T(1<=T<=100),代表測試資料的數量.每個測試資料的第一行是一個正整數N(1<=N<=1000),代表矩形的數量,然後是N行資料,每一行包含四個浮點數,代表平面上的一個矩形的左上方座標和右下角座標,矩形的上下邊和X軸平行,左右邊和Y軸平行.座標的範圍從0到100000.
注意:本題的輸入資料較多,推薦使用scanf讀入資料.
Output對於每組測試資料,請計算出被這些矩形覆蓋過至少兩次的地區的面積.結果保留兩位小數.
Sample Input
251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 0 2 12 0 3 1
Sample Output
7.630.00本部落格有掃描線方面的詳盡解答,包括這道題目以及一般的掃描線,如果讀者需要請到部落格中http://blog.csdn.net/qq_18661257/article/details/47658191#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;typedef long long LL;#define lson rt << 1, l, mid#define rson rt << 1|1, mid + 1, rconst int MAXN = 2000 + 5;int Col[MAXN << 2], n, cnt, res, T;double X[MAXN << 2], Sum[MAXN << 2],Sum2[MAXN << 2];struct seg { double l,r,h; int s; seg() {} seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s) {} bool operator < (const seg & object) const { return h < object.h; }} S[MAXN];void pushup(int rt,int l,int r) { if(Col[rt]) Sum[rt] = X[r + 1] - X[l]; else if(l == r) Sum[rt] = 0; else Sum[rt] = Sum[rt << 1] + Sum[rt << 1|1]; if(Col[rt] >= 2) Sum2[rt] = X[r + 1] - X[l]; else if(l == r) Sum2[rt] = 0; else if(Col[rt] == 1) Sum2[rt] = Sum[rt << 1] + Sum[rt << 1|1]; else if(Col[rt] == 0) Sum2[rt] = Sum2[rt << 1] + Sum2[rt << 1|1];}void update(int L, int R, int c,int rt,int l, int r) { if(L <= l && r <= R) { Col[rt] += c; pushup(rt,l,r); return ; } int mid = (l + r) >> 1; if(L <= mid) update(L, R, c, lson); if(R > mid) update(L, R, c, rson); pushup(rt,l,r);}int binary_find(double x) { int lb = -1,ub = res - 1; while(ub - lb > 1) { int mid = (lb + ub) >> 1; if(X[mid] >= x) ub = mid; else lb = mid; } return ub;}int main() { scanf("%d", &T); while(T --) { scanf("%d", &n); cnt = res = 0; for(int i = 0 ; i < n; i ++) { double a,b,c,d; scanf("%lf%lf%lf%lf",&a, &b, &c,&d); S[cnt] = seg(a, c, b, 1); X[cnt ++] = a; S[cnt] = seg(a, c, d, -1); X[cnt ++] = c; } sort(X, X + cnt); sort(S, S + cnt); res ++; for(int i = 1; i < cnt; i ++) { if(X[i] != X[i - 1]) X[res ++] = X[i]; } memset(Sum, 0, sizeof(Sum)); memset(Col, 0, sizeof(Col)); memset(Sum2,0,sizeof(Sum2)); double ans = 0; for(int i = 0; i < cnt - 1; i ++) { int l = binary_find(S[i].l); int r = binary_find(S[i].r) - 1;//利用[ , ),這個區間性質,左閉右開 update(l, r, S[i].s, 1, 0, res - 1); ans += Sum2[1] * (S[i + 1].h - S[i].h); } printf("%.2lf\n", ans); } return 0;}
|