题目链接:https://vjudge.net/contest/332656#problem/J
思路:
这道题的大体的思路其实还是扫描线的思路。 就是我们要清晰之前我们所说的len 代表的是被覆盖了一次及以上次数的线段长度
为叙述方便,我们假设len[2]为当前线段被覆盖了两次的长度,len[1]为当前线段被覆盖了一次的长度,而len[0]就是这条线段的长度,并且满足len[2]+len[1]=len[0]。
首先,如果当前这条线段已经被覆盖了两次了,那么这条线段的len[2]就应该等于len[0],而len[1]就应该等于0。
其次,如果当前这条线段被覆盖了一次,那么这条线段的len[2]就应该是,左右子线段的len[2]的和加上左右子线段的len[1],当然,前提是当前线段不能是线段树中的叶子结点,否则它就没有左右子线段不是吗?这时候,当前线段的len[2]就应该等于0。而len[1]就等于len[0],最后要注意当前线段的len[1]要减去len[2],以满足len[1]+len[2]=len[0]。
最后,如果这条线段没有被覆盖过,并且当前线段不是线段树里的叶子结点,那么它的len[1]和len[2]都应该从它的左右子线段的len[1]和len[2]得到,如果是叶子结点,那么len[1]和len[2]都等0。
因为采用的是魔改的线段树 所以叶子结点需要多开一个标记
1 #include <math.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <iostream>
5 #include <algorithm>
6 #include <string>
7 #include <string.h>
8 #include <vector>
9 #include <map>
10 #include <stack>
11 #include <set>
12 #include <random>
13
14 #define LL long long
15 #define ls nod<<1
16 #define rs (nod<<1)+1
17 const int maxn = 2e5 + 10;
18 const double eps = 1e-9;
19
20 double v[maxn];
21
22 struct L {
23 double x;
24 double y1,y2;
25 int state;
26 bool operator <(const L &ith) const{
27 return x<ith.x;
28 }
29 }line[maxn];
30
31 struct segment_tree {
32 double l,r;
33 int cover;
34 double len[3];
35 bool flag;
36 void init() {
37 memset(len,0, sizeof(len));
38 }
39 }tree[maxn<<3];
40
41 void pushup(int nod) {
42 if (tree[nod].cover) {
43 tree[nod].len[0] = tree[nod].r - tree[nod].l;
44 }
45 else
46 tree[nod].len[0] = tree[ls].len[0] + tree[rs].len[0];
47
48 if (tree[nod].cover >= 2) {
49 tree[nod].len[2] = tree[nod].len[0];
50 tree[nod].len[1] = 0;
51 }
52 else if (tree[nod].cover == 1) {
53 if (tree[nod].flag) {
54 tree[nod].len[2] = 0;
55 }
56 else {
57 tree[nod].len[2] = (tree[ls].len[2] + tree[rs].len[2] + tree[ls].len[1] + tree[rs].len[1]);
58 }
59 tree[nod].len[1] = tree[nod].len[0];
60 tree[nod].len[1] -= tree[nod].len[2];
61 }
62 else {
63 if (tree[nod].flag) {
64 tree[nod].len[2] = tree[nod].len[1] = 0;
65 }
66 else {
67 tree[nod].len[2] = tree[ls].len[2] + tree[rs].len[2];
68 tree[nod].len[1] = tree[ls].len[1] + tree[rs].len[1];
69 }
70 }
71 }
72
73 void build(int l,int r,int nod=1) {
74 tree[nod].l = v[l];
75 tree[nod].r = v[r];
76 tree[nod].init();
77 tree[nod].cover = 0;
78 tree[nod].flag = false;
79 if (r-l <= 1) {
80 tree[nod].flag = true;
81 return;
82 }
83 int mid = (l + r) >> 1;
84 build(l,mid,ls);
85 build(mid,r,rs);
86 }
87
88 void modify(double x,double y,int z,int nod=1) {
89 double l = tree[nod].l,r = tree[nod].r;
90 if (x <= l && y >= r){
91 tree[nod].cover += z;
92 pushup(nod);
93 return ;
94 }
95 if (x < tree[ls].r)
96 modify(x,y,z,ls);
97 if (y > tree[rs].l)
98 modify(x,y,z,rs);
99 pushup(nod);
100 }
101
102 int main() {
103 int T;
104 scanf("%d",&T);
105 while (T--) {
106 int n;
107 double a, b, c, d;
108 scanf("%d",&n);
109 for (int i = 1; i <= n; i++) {
110 scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
111 v[i] = b;
112 v[n + i] = d;
113 line[i].x = a;
114 line[i].y1 = b;
115 line[i].y2 = d;
116 line[i].state = 1;
117 line[i+n].x = c;
118 line[i+n].y1 = b;
119 line[i+n].y2 = d;
120 line[i+n].state = -1;
121 }
122 std::sort(v + 1, v + 1 + (n << 1));
123 std::sort(line + 1, line + 1 + (n << 1));
124 build(1, n << 1);
125 double ans = 0.0;
126 for (int i = 1; i <= 2 * n; i++) {
127 ans += tree[1].len[2] *(line[i].x - line[i-1].x);
128 //printf("%lf\n",tree[1].len[2]);
129 modify(line[i].y1, line[i].y2, line[i].state);
130 }
131 printf("%.2lf\n",ans);
132 }
133 return 0;
134 }