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 }