HDU 1255(扫描线、线段树区间修改)

Problem - 1255 (hdu.edu.cn)

题意

在二维平面坐标轴上输入n个矩形,问被这n个矩形覆盖了两次或两次以上的区域的面积总和。

给的题意有点问题,实际输入是矩形的左下和右上,另外样例1应该输出7.62.

思路

扫描线,这里是沿着x轴正方向每次用一条垂直于x轴的直线去扫,离散化y坐标的值,用线段树维护y坐标上合法区间的和。注意,我们线段树实际要维护的是y坐标间的线段长度,注意到n个点组成的n-1个线段区间,需要将[0,n]的下标转化为[1,n-1]的线段树所管理的区间上,之后再维护线段树。用c1表示被覆盖了1次的区间,c2表示被覆盖了2次的区间。其余就是线段树通用操作了。

 

 1 #define IO std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
 2 #define bug(x) cout<<#x<<" is "<<x<<endl;
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #include<vector>
 7 #include<tuple>
 8 #define rs o*2+1
 9 #define ls o*2
10 using namespace std;
11 const int N=1e4+5;
12 int T, n, add[N*4];
13 double c1[N*4], c2[N*4];
14 vector <tuple<double, double, double, int>> v;
15 vector <double> id;
16 void push_up(int o, int l, int r){
17     if (add[o] >= 2) c2[o] = id[r]-id[l-1];
18     else if (add[o] == 1) c2[o] = c1[ls] + c1[rs];
19     else if (r != l) c2[o] = c2[ls] +c2[rs];
20     else c2[o] = 0;
21     if (add[o]) c1[o] = id[r]-id[l-1];
22     else if (r != l) c1[o] =  c1[ls] +c1[rs];
23     else c1[o] = 0;
24 }
25 void up(int o, int l, int r, int ql, int qr, int d){
26     if (l >= ql && r <= qr){
27         add[o] += d;
28         push_up(o, l, r);
29         return;
30     }
31     int m = (l+r)/2;
32     if (ql <= m) up(ls, l, m, ql, qr, d);
33     if (qr > m) up(rs, m+1, r, ql, qr, d);
34     push_up(o, l, r);
35 }
36 int gao(double x){
37     return lower_bound(id.begin(), id.end(), x)-id.begin();
38 }
39 int main(){
40     IO;
41     cin >> T;
42     while (T--){
43         cin >> n;
44         double l, r, d, u;
45         id.clear();
46         v.clear();
47         for (int i = 0; i < n; i++){
48             cin >> l >> d >> r >> u;
49             id.push_back(d);
50             id.push_back(u);
51             v.push_back(make_tuple(l, d, u, 1));
52             v.push_back(make_tuple(r, d, u, -1));
53         }
54         sort(id.begin(), id.end());
55         id.erase(unique(id.begin(), id.end()), id.end());
56         sort(v.begin(), v.end());
57         double pre = 0, ans = 0;
58         for (auto i:v){
59             double pos = get<0>(i), d = get<1>(i), u = get<2>(i);
60             int del = get<3>(i);
61             ans += (pos-pre)*c2[1];
62             pre = pos;
63             up(1, 1, id.size()-1, gao(d)+1, gao(u), del);
64         }
65         printf("%.2f\n", ans);
66     }
67 }

 

posted @ 2024-06-12 08:32  Venux  阅读(10)  评论(0编辑  收藏  举报