[线段树]picture

PICTURE

题目描述

N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上。它们的边都是垂直的或水平的。每个矩形可以部分或者全部覆盖其他矩形。所有的矩形组成的集合的轮廓称为周长。写一个程序计算周长。

图 1 是一个有 7 个矩形的例子:

图 1.一个 7 个矩形的集合对应的轮廓为图 2 所示的所有线段的集合:

图 2. 矩形集合的轮廓

所有矩形的顶点坐标均为整数。所有的坐标都在 [-10000,10000] 的范围内,并且任何一个矩形面积都为整数。结果的值可能需要 32 位有符号整数表示。

输入

第1行: N,张贴在墙上的矩形的数目。 第 2..N+1行 接下来的N行中,每行都有两个点的坐标,分别是矩形的左下角坐标和右上角坐标。每一个坐标由 X 坐标和 Y 坐标组成。

输出

只有一行,为一个非负整数,表示输入数据中所有矩形集合的轮廓长度。

样例输入

7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16

样例输出

228




自己写(chao)的,并没有用线段树维护,加了快读8ms
 1 #include <cstdio> 
 2 #include <algorithm> 
 3 #include <cstring> 
 4 using namespace std; 
 5     
 6 struct data { 
 7     int lx, rx; 
 8     int ly, ry; 
 9 }; 
10     
11 const int maxn = 5000, maxx = 20000; 
12 int n; 
13 data a[maxn + 1]; 
14 int level[maxx + 1]; 
15     
16 bool cmp_x(data x, data y) { 
17     return x.lx < y.lx; 
18 } 
19     
20 bool cmp_y(data x, data y) { 
21     return x.ly < y.ly; 
22 } 
23     
24 int in() { 
25     int f = 1, p = 0;     
26     char c; 
27     while (c < '0' || c > '9') {
28         c = getchar(); 
29         if (c == '-') {
30             f = -1; 
31         }
32     }
33     while (c >= '0' && c <= '9') {
34         p = p * 10 + c - '0'; 
35         c = getchar(); 
36     }
37     p *= f; 
38     return p; 
39 } 
40     
41 void init() { 
42     n = in(); 
43     for (int i = 1; i <= n; i++) { 
44         a[i].lx = in();
45         a[i].ly = in();
46         a[i].rx = in();
47         a[i].ry = in();  
48         a[i].lx += 10001; 
49         a[i].ly += 10001; 
50         a[i].rx += 10001; 
51         a[i].ry += 10001; 
52     } 
53 } 
54     
55 int solve_x() { 
56     memset(level, -1, sizeof(level)); 
57     int ans = 0; 
58     sort(a + 1, a + 1 + n, cmp_x); 
59     for (int i = 1; i <= n; i++) {
60         for (int j = a[i].ly; j < a[i].ry; j++) { 
61             if (level[j] < a[i].lx) {
62                 ans += 2; 
63             }
64             if (level[j] < a[i].rx) {
65                 level[j] = a[i].rx; 
66             }
67         } 
68     }
69     return ans; 
70 } 
71     
72 int solve_y() { 
73     memset(level, -1, sizeof(level)); 
74     int ans = 0; 
75     sort(a + 1, a + 1 + n, cmp_y); 
76     for (int i = 1; i <= n; i++) {
77         for (int j = a[i].lx; j < a[i].rx; j++) { 
78             if (level[j] < a[i].ly) { 
79                 ans += 2; 
80             }
81             if (level[j] < a[i].ry) {
82                 level[j] = a[i].ry; 
83             }
84         } 
85     }
86     return ans; 
87 } 
88     
89 int main() { 
90     init(); 
91     printf("%d
", solve_x() + solve_y()); 
92     return 0; 
93 } 

下面是学长的QAQQ用了线段树维护

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define MN 10000
  4 #define MX 20000
  5 #define L (k << 1)
  6 #define R ((k << 1) + 1)
  7 using namespace std; 
  8 
  9 struct work{    //扫描线 
 10     int x, l, r, p; 
 11 }x[MN + 5], y[MN + 5];
 12 
 13 bool cmp(work a, work b){
 14     return a.x == b.x ? a.p > b.p : a.x < b.x; 
 15 }
 16 
 17 struct data{
 18     int x, s; 
 19 };
 20 
 21 data operator + (data a, data b){
 22     if (a.x == b.x) {
 23         return (data) {
 24             a.x, a.s + b.s
 25         };
 26     }
 27     return a.x < b.x ? a : b; 
 28 }
 29 
 30 struct node{
 31     int l, r, mk;
 32     data x;
 33 }t[MX * 4 + 5]; 
 34 
 35 inline void up (int k){
 36     t[k].x = t[L].x + t[R].x; 
 37 }
 38 
 39 inline void add(int k, int x){
 40     t[k].x.x += x; 
 41     t[k].mk += x; 
 42 }
 43 
 44 inline void down(int k){
 45     if (t[k].mk) {
 46         add(L, t[k].mk); 
 47         add(R, t[k].mk); 
 48         t[k].mk = 0; 
 49     }
 50 }
 51 
 52 void build(int k, int l, int r) {
 53     t[k].l = l; 
 54     t[k].r = r; 
 55     if (l == r) {
 56         t[k].x.s = 1; 
 57         return; 
 58     }
 59     int mid = l + r >> 1;  
 60     build(L, l, mid); 
 61     build(R, mid + 1, r); 
 62     up(k); 
 63 }
 64 
 65 void renew(int k, int l, int r, int x) {
 66     if (t[k].l == l && t[k].r == r) {
 67         add(k, x); 
 68         return; 
 69     }
 70     down(k); 
 71     int mid = t[k].l + t[k].r >> 1; 
 72     if (r <= mid) {
 73         renew(L, l, r, x); 
 74     }
 75     else if (l > mid) {
 76         renew(R, l, r, x); 
 77     }
 78     else {
 79         renew(L, l, mid, x); 
 80         renew(R, mid + 1, r, x); 
 81     }
 82     up(k); 
 83 }
 84 
 85 data query(int k, int l, int r){
 86     if (t[k].l == l && t[k].r == r) {
 87         return t[k].x; 
 88     }
 89     down(k); 
 90     int mid = (t[k].l + t[k].r) >> 1; 
 91     if (r <= mid) {
 92         return query(L, l, r); 
 93     }
 94     if (l > mid) {
 95         return query(R, l, r); 
 96     }
 97     return query(L, l, mid) + query(R, mid + 1, r); 
 98 }
 99 int n, ans; 
100 void solve (work *x) {
101     for (int i = 0; i < n; i++) {
102         if (x[i].p < 0) {
103             renew(1, x[i].l, x[i].r, -1); 
104         }
105         data d = query(1, x[i].l, x[i].r); 
106         if (x[i].p > 0) {
107             renew(1, x[i].l, x[i].r, 1); 
108         }
109         ans += d.x ? 0 : d.s; 
110     }
111 }
112 
113 int main(){
114     int i, x0, y0, x1, y1; 
115     scanf("%d", &n); 
116     for (int i = 0; i < n; ++i) {
117         scanf("%d%d%d%d", &x0, &y0, &x1, &y1); 
118         x0 += MN; 
119         y0 += MN; 
120         x1 += MN; 
121         y1 += MN; 
122         x[i] = (work) {
123             y0, x0, x1 - 1, 1
124         }; 
125         x[i + n] = (work) {
126             y1, x0, x1 - 1, -1
127         }; 
128         y[i] = (work) {
129             x0, y0, y1 - 1, 1
130         }; 
131         y[i + n] = (work) {
132             x1, y0, y1 - 1, -1
133         };
134     }
135     n <<= 1; 
136     sort(x, x + n, cmp); 
137     sort(y, y + n, cmp); 
138     build(1, 0, MX); 
139     solve(x); 
140     solve(y); 
141     printf("%d", ans); 
142     return 0; 
143 }


原文地址:https://www.cnblogs.com/GldHkkowo/p/8857297.html