HDU1542矩形面积并
取出纵向边按x坐标排序,在y方向上建立线段树。
每次查询当前有效长度len,ans += len*(x[i]-x[i-1]); 其中len为T[rt].len;
查询完毕后更新y方向上线段树,入边+1, 出边-1。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define lson l, m, rt<<1 4 #define rson m+1, r, rt<<1|1 5 typedef long long ll; 6 struct L{ 7 double x, y1, y2; 8 int d; 9 L(){} 10 L(double x, double y1, double y2, int d): x(x), y1(y1), y2(y2), d(d){} 11 }; 12 L line[500]; 13 bool cmp(L A, L B){ 14 return A.x < B.x; 15 } 16 double y[500]; 17 18 struct Node{ 19 int d; 20 double len; 21 }; 22 Node T[500<<3]; 23 void init(){ 24 memset(T, 0, sizeof(T)); 25 } 26 void pushup(int rt, int l, int r){ 27 if(T[rt].d) 28 T[rt].len = y[r]-y[l-1]; 29 else 30 T[rt].len = l == r? 0 : T[rt<<1].len+T[rt<<1|1].len; 31 } 32 void update(int L, int R, int d, int l, int r, int rt){ 33 if(L <= l&&r <= R){ 34 T[rt].d += d; 35 pushup(rt, l , r); 36 return ; 37 } 38 int m = (l+r)>>1; 39 if(L <= m) update(L, R, d, lson); 40 if(R > m) update(L, R, d, rson); 41 pushup(rt, l, r); 42 } 43 44 int main(){ 45 int n, ca = 1; 46 double x1, y1, x2, y2; 47 while(scanf("%d", &n), n){ 48 for(int i = 0; i < n; i++){ 49 scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); 50 line[i*2] = L(x1, y1, y2, 1); 51 line[i*2+1] = L(x2, y1, y2, -1); 52 y[i*2] = y1, y[i*2+1] = y2; 53 } 54 sort(line, line+2*n, cmp); 55 sort(y, y+2*n); 56 57 init(); 58 double ans = 0; 59 for(int i = 0; i < 2*n; i++){ 60 if(i&&line[i].x != line[i-1].x) 61 ans += (line[i].x-line[i-1].x)*T[1].len; 62 int l = lower_bound(y, y+2*n, line[i].y1)-y+1, r = lower_bound(y, y+2*n, line[i].y2)-y; 63 if(l <= r) 64 update(l, r, line[i].d, 1, 2*n, 1); 65 } 66 printf("Test case #%d\n", ca++); 67 printf("Total explored area: %.2f\n\n", ans); 68 } 69 return 0; 70 }
无pushdown()函数,每条线段只存一次。d表示被覆盖的次数,len表示至少被覆盖一次的合法长度。详见pushup()函数。
ans += T[1].len*(x[i]-x[i-1]);
求面积交:方法同求面积并,外加len2表示至少被覆盖两次的合法长度,ans += T[1].len2*(x[i]-x[i-1]);
求周长并:方法同面积并,扫描两次,分别沿x方向和y方向,每次加上 更新前后T[1].len的差值的绝对值。
诸神对凡人心生艳羡,厌倦天堂。