扫描线

POJ 1151 Atlantis

扫描线求矩形面积并。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <vector>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define inf 0x3f3f3f3f
13 #define lson l, m, rt << 1
14 #define rson m+1, r, rt << 1 | 1
15 #define mnx 1100
16 
17 double x[mnx], sum[mnx];
18 int vis[mnx];
19 struct edge{
20     double l, r, h;
21     int s;
22     edge(){}
23     edge( double l, double r, double h, int s ) : l(l), r(r), h(h), s(s) {}
24     bool operator < ( const edge &b ) const {
25         return h < b.h;
26     }
27 }e[mnx];
28 void pushup( int rt, int l, int r ){
29     if( vis[rt] ) sum[rt] = x[r+1] - x[l];
30     else if( l == r ) sum[rt] = 0;
31     else sum[rt] = sum[rt<<1] + sum[rt<<1|1];
32 }
33 void update( int L, int R, int v, int l, int r, int rt ){
34     if( L <= l && R >= r ){
35         vis[rt] += v;
36         pushup( rt, l, r );
37         return ;
38     }
39     int m = ( l + r ) >> 1;
40     if( L <= m ) update( L, R, v, lson );
41     if( R > m ) update( L, R, v, rson );
42     pushup( rt, l, r );
43 }
44 int bin( double v, int L, int R ){
45     int l = L, r = R;
46     while( l < r ){
47         int m = ( l + r ) >> 1;
48         if( x[m] >= v ) r = m;
49         else l = m + 1;
50     }
51     return l;
52 }
53 int main(){
54     int n, m, k, kk = 0;
55     while( scanf( "%d", &n ) != EOF && n ){
56         printf( "Test case #%d\n", ++kk );
57         memset( vis, 0, sizeof vis );
58         for( int i = 0; i < mnx; ++i )
59             sum[i] = 0;
60         m = 0, k = 1;
61         for( int i = 0; i < n; ++i ){
62             double ax, ay, bx, by;
63             scanf( "%lf %lf %lf %lf", &ax, &ay, &bx, &by );
64             x[m] = ax, e[m++] = edge( ax, bx, ay, 1 );
65             x[m] = bx, e[m++] = edge( ax, bx, by, -1 );
66         }
67         sort( x, x + m );
68         sort( e, e + m );
69         for( int i = 1; i < m; ++i )
70             if( x[i] != x[i-1] ) x[k++] = x[i];
71         double ans = 0;
72         for( int i = 0; i < m-1; ++i ){
73             int l = bin( e[i].l, 0, k-1 );
74             int r = bin( e[i].r, 0, k-1 ) - 1;
75             if( l <= r ) update( l, r, e[i].s, 0, k-1, 1 );
76             ans += sum[1] * ( e[i+1].h - e[i].h );
77         }
78         printf( "Total explored area: %.2lf\n\n", ans );
79     }
80     return 0;
81 }
View Code

POJ 1177 Picture

扫描线求矩形周长并。思路:与面积不同的地方是还要记录竖的边有几个(numseg记录),并且当边界重合的时候需要合并(用lbd和rbd表示边界来辅助) 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <queue>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt << 1
13 #define rson m + 1, r, rt << 1 | 1
14 #define inf 0x3f3f3f3f
15 #define mnx 23000
16 
17 int len[mnx<<2], cnt[mnx<<2], segsum[mnx<<2];
18 bool lbd[mnx<<2], rbd[mnx<<2];
19 struct edge{
20     int l, r, h, s;
21     edge(){}
22     edge( int l, int r, int h, int s ) : l(l), r(r), h(h), s(s) {}
23     bool operator < ( const edge &b ) const {
24         return h < b.h || ( h == b.h && s > b.s );
25     }
26 }e[mnx];
27 void pushup( int rt, int l, int r ){
28     if( cnt[rt] ){
29         len[rt] = r - l + 1;
30         segsum[rt] = 2;
31         lbd[rt] = rbd[rt] = 1;
32     }
33     else if( l == r ){
34         len[rt] = segsum[rt] = lbd[rt] = rbd[rt] = 0;
35     }
36     else{
37         len[rt] = len[rt<<1] + len[rt<<1|1];
38         segsum[rt] = segsum[rt<<1] + segsum[rt<<1|1];
39         lbd[rt] = lbd[rt<<1];
40         rbd[rt] = rbd[rt<<1|1];
41         if( rbd[rt<<1] && lbd[rt<<1|1] ) segsum[rt] -= 2;
42     }
43 }
44 void update( int L, int R, int v, int l, int r, int rt ){
45     if( L <= l && R >= r ){
46         cnt[rt] += v;
47         pushup( rt, l, r );
48         return ;
49     }
50     int m = ( l + r ) >> 1;
51     if( L <= m ) update( L, R, v, lson );
52     if( R > m ) update( L, R, v, rson );
53     pushup( rt, l, r );
54 }
55 int main(){
56     int n, m;
57     while( scanf( "%d", &n ) != EOF ){
58         m = 0;
59         int lmin = inf, rmax = -inf;
60         for( int i = 0; i < n; ++i ){
61             int ax, ay, bx, by;
62             scanf( "%d%d%d%d", &ax, &ay, &bx, &by );
63             e[m++] = edge( ax, bx, ay, 1 );
64             e[m++] = edge( ax, bx, by, -1 );
65             lmin = min( lmin, ax );
66             rmax = max( rmax, bx );
67         }
68         sort( e, e + m );
69         int ans = 0, pre = 0;
70         for( int i = 0; i < m; ++i ){
71             if( e[i].l < e[i].r )
72                 update( e[i].l, e[i].r-1, e[i].s, lmin, rmax-1, 1 );
73             ans += segsum[1] * ( e[i+1].h - e[i].h );
74             ans += abs( len[1] - pre );
75             pre = len[1];
76         }
77         printf( "%d\n", ans );
78     }
79     return 0;
80 }
View Code

POJ 1389 Area of Simple Polygons

矩形面积并。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <queue>
 7 
 8 using namespace std;
 9 
10 #define LL long long
11 #define eps 1e-8
12 #define lson l, m, rt << 1
13 #define rson m + 1, r, rt << 1 | 1
14 #define inf 0x3f3f3f3f
15 #define mnx 53000
16 
17 struct edge{
18     int l, r, h, s;
19     edge () {}
20     edge( int l, int r, int h, int s ) : l(l), r(r), h(h), s(s) {}
21     bool operator < ( const edge &b ) const {
22         return h < b.h || ( h == b.h && s > b.s );
23     }
24 }e[mnx];
25 int cnt[mnx<<2], len[mnx<<2];
26 void pushup( int rt, int l, int r ){
27     if( cnt[rt] ){
28         len[rt] = r - l + 1;
29     }
30     else if( l == r )
31         len[rt] = 0;
32     else
33         len[rt] = len[rt<<1] + len[rt<<1|1];
34 }
35 void update( int L, int R, int v, int l, int r, int rt ){
36     if( L <= l && R >= r ){
37         cnt[rt] += v;
38         pushup( rt, l, r );
39         return ;
40     }
41     int m = ( l + r ) >> 1;
42     if( L <= m ) update( L, R, v, lson );
43     if( R > m ) update( L, R, v, rson );
44     pushup( rt, l, r );
45 }
46 int main(){
47     int ax, ay, bx, by;
48     while( scanf( "%d%d%d%d", &ax, &ay, &bx, &by ) != EOF ){
49         if( ax == -1 && ay == -1 && bx == -1 && by == -1 ) break;
50         int m = 0;
51         e[m++] = edge( ax, bx, ay, 1 );
52         e[m++] = edge( ax, bx, by, -1 );
53         while( scanf( "%d%d%d%d", &ax, &ay, &bx, &by ) ){
54             if( ax == -1 && ay == -1 && bx == -1 && by == -1 ) break;
55             e[m++] = edge( ax, bx, ay, 1 );
56             e[m++] = edge( ax, bx, by, -1 );
57         }
58         sort( e, e + m );
59         int ans = 0;
60         for( int i = 0; i < m; ++i ){
61             if( e[i].l < e[i].r )
62                 update( e[i].l, e[i].r-1, e[i].s, 0, 50000, 1 );
63             //printf( "%d %d %d\n", len[1], e[i+1].h, e[i].h );
64             ans += len[1] * ( e[i+1].h - e[i].h );
65         }
66         printf( "%d\n", ans );
67     }
68     return 0;
69 }
View Code

fzu 2187 回家种地

求只覆盖了一次的矩形的面积。思路,也是矩形面积并。记录覆盖一次以上sum[]和覆盖两次以上more[]的区间长度,然后sum[1] - more[1]就是覆盖一次的区间长度。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<vector>
 7 #include<queue>
 8 
 9 using namespace std;
10 
11 #define inf 1e16
12 #define eps 1e-6
13 #define LL long long
14 #define ULL unsigned long long
15 #define MP make_pair
16 #define pb push_back
17 #define mod 1000000009
18 #define lson l, m, rt<<1
19 #define rson m+1, r, rt<<1|1
20 #define mnx 200050
21 
22 struct edge{
23     int ax, bx, y, s;
24     edge( int ax = 0, int bx = 0, int y = 0, int s = 0 ) : ax(ax), bx(bx), y(y), s(s) {}
25     bool operator < ( const edge &b ) const {
26         return y < b.y || y == b.y && s > b.s;
27     }
28 }e[mnx];
29 int x[mnx], vis[mnx<<1];
30 LL sum[mnx<<1], more[mnx<<1];
31 void pushup( int rt, int l, int r ){
32     if( vis[rt] >= 2 ){
33         sum[rt] = more[rt] = x[r+1] - x[l];
34     }
35     else if( vis[rt] == 1 ){
36         sum[rt] = x[r+1] - x[l];
37         if( l == r ) more[rt] = 0;
38         else more[rt] = sum[rt<<1] + sum[rt<<1|1];
39     }
40     else{
41         if( l == r ) sum[rt] = more[rt] = 0;
42         else{
43             sum[rt] = sum[rt<<1] + sum[rt<<1|1];
44             more[rt] = more[rt<<1] + more[rt<<1|1];
45         }
46     }
47 }
48 void update( int L, int R, int s, int l, int r, int rt ){
49     if( L <= l && R >= r ){
50         vis[rt] += s;
51         pushup( rt, l, r );
52         return ;
53     }
54     int m = ( l + r ) >> 1;
55     if( L <= m ) update( L, R, s, lson );
56     if( R > m ) update( L, R, s, rson );
57     pushup( rt, l, r );
58 }
59 int bin( int val, int l, int r ){
60     while( l < r ){
61         int m = ( l + r ) >> 1;
62         if( x[m] >= val ) r = m;
63         else l = m+1;
64     }
65     return l;
66 }
67 int main(){
68     int cas, kk = 1;
69     scanf( "%d", &cas );
70     while( cas-- ){
71         memset( vis, 0, sizeof(vis) );
72         memset( sum, 0, sizeof(sum) );
73         memset( more, 0, sizeof(more) );
74         int n;
75         scanf( "%d", &n );
76         for( int i = 0; i < n; ++i ){
77             int ax, ay, bx, by;
78             scanf( "%d%d%d%d", &ax, &ay, &bx, &by );
79             x[i] = ax, e[i] = edge( ax, bx, ay, 1 );
80             x[i+n] = bx, e[i+n] = edge( ax, bx, by, -1 );
81         }
82         n <<= 1;
83         sort( x, x + n );
84         sort( e, e + n );
85         int m = unique( x, x + n ) - x;
86         LL ans = 0;
87         for( int i = 0; i < n-1; ++i ){
88             int l = bin( e[i].ax, 0, m-1 );
89             int r = bin( e[i].bx, 0, m-1 ) - 1;
90             if( l <= r ) update( l, r, e[i].s, 0, m-1, 1 );
91             //cout << sum[1] << " " << more[1] << endl;
92             ans += (LL)( sum[1] - more[1] ) * ( e[i+1].y - e[i].y );
93         }
94         printf( "Case %d: %I64d\n", kk++, ans );
95     }
96     return 0;
97 }
View Code

 

转载于:https://www.cnblogs.com/LJ-blog/p/4360741.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值