HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和。

因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <map>
 5 #include <algorithm>
 6 using namespace std;
 7 const int MAXN = 4e3 + 5;
 8 struct data {
 9     int x1 , x2 , flag;
10     double y , xx1 , xx2;
11     bool operator <(const data& cmp) const {
12         return y < cmp.y;
13     }
14 }a[MAXN];
15 struct segtree {
16     int l , r , add;
17     double val;
18 }T[MAXN << 2];
19 double x[MAXN];
20 map <double , int> mp;
21 
22 void build(int p , int l , int r) {
23     int mid = (l + r) >> 1;
24     T[p].val = T[p].add = 0 , T[p].l = l , T[p].r = r;
25     if(r - l == 1) {
26         return ;
27     }
28     build(p << 1 , l , mid);
29     build((p << 1)|1 , mid , r);
30 }
31 
32 void updata(int p , int l , int r , int val) {
33     int mid = (T[p].l + T[p].r) >> 1;
34     if(T[p].r - T[p].l == 1) {
35         T[p].add += val;
36         if(T[p].add > 1)
37             T[p].val = x[T[p].r] - x[T[p].l];
38         else
39             T[p].val = 0;
40         return ;
41     }
42     if(r <= mid) {
43         updata(p << 1 , l , r , val);
44     }
45     else if(l >= mid) {
46         updata((p << 1)|1 , l , r , val);
47     }
48     else {
49         updata(p << 1 , l , mid , val);
50         updata((p << 1)|1 , mid , r , val);
51     }
52     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
53 }
54 
55 int main()
56 {
57     int t = 1 , n;
58     double x1 , x2 , y1 , y2;
59     scanf("%d" , &t);
60     while(t--) {
61         mp.clear();
62         scanf("%d" , &n);
63         int cnt = 0;
64         for(int i = 0 ; i < n ; i++) {
65             scanf("%lf %lf %lf %lf" , &x1 , &y1 , &x2 , &y2);
66             if(x1 > x2)
67                 swap(x1 , x2);
68             if(y1 > y2)
69                 swap(y1 , y2);
70             int ls = i * 2 , rs = i * 2 + 1;
71             a[ls].xx1 = x1 , a[ls].xx2 = x2 , a[ls].y = y1 , a[ls].flag = 1;
72             a[rs].xx1 = x1 , a[rs].xx2 = x2 , a[rs].y = y2 , a[rs].flag = -1;
73             if(!mp[x1]) {
74                 mp[x1] = 1;
75                 x[++cnt] = x1;
76             }
77             if(!mp[x2]) {
78                 mp[x2] = 1;
79                 x[++cnt] = x2;
80             }
81         }
82         sort(a , a + n * 2);
83         sort(x + 1 , x + cnt + 1);
84         for(int i = 0 ; i < n * 2 ; i++) {
85             a[i].x1 = lower_bound(x + 1 , x + cnt + 1 , a[i].xx1) - x;
86             a[i].x2 = lower_bound(x + 1 , x + cnt + 1 , a[i].xx2) - x;
87         }
88         double res = 0;
89         build(1 , 1 , cnt);
90         updata(1 , a[0].x1 , a[0].x2 , a[0].flag);
91         for(int i = 1 ; i < 2 * n ; i++) {
92             res += (a[i].y - a[i - 1].y) * T[1].val;
93             updata(1 , a[i].x1 , a[i].x2 , a[i].flag);
94         }
95         printf("%.2f\n" , res);
96     }
97 }

 

转载于:https://www.cnblogs.com/Recoder/p/5443879.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值