题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642
题目大意:给你n个立方体,求相交区域大于等于三次的体积和。
题目思路:同样的利用二维扫描线去维护xOy平面的矩形的面积。 然后对于每个不同的z找到符合要求的长方体
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <map> 6 using namespace std; 7 const int N = 2005; 8 struct Line { 9 int lx, h1, h2; 10 int flag; 11 Line(int a, int b, int c, int d):lx(a), h1(b), h2(c), flag(d) {} 12 bool operator < (const Line &a) const { return lx < a.lx; } 13 }; 14 int n, flag[N << 2], cube[N][6]; 15 int tree[4][N << 2]; 16 vector<int> a, b; 17 vector<Line> line; 18 map<int, int> mp; 19 20 void pushup(int k, int left, int right) { 21 if (flag[k] > 2) { 22 tree[3][k] = tree[0][k]; 23 tree[2][k] = tree[1][k] = 0; 24 } 25 else if (flag[k] == 2) { 26 if (left + 1 == right) { 27 tree[2][k] = tree[0][k]; 28 tree[1][k] = tree[3][k] = 0; 29 } 30 else { 31 tree[3][k] = tree[3][k * 2] + tree[3][k * 2 + 1] + tree[2][k * 2] + tree[2][k * 2 + 1] + tree[1][k * 2] + tree[1][k * 2 + 1]; 32 tree[2][k] = tree[0][k] - tree[3][k]; 33 tree[1][k] = 0; 34 } 35 } 36 else if (flag[k] == 1) { 37 if (left + 1 == right) { 38 tree[1][k] = tree[0][k]; 39 tree[2][k] = tree[3][k] = 0; 40 } 41 else { 42 tree[3][k] = tree[3][k * 2] + tree[3][k * 2 + 1] + tree[2][k * 2] + tree[2][k * 2 + 1]; 43 tree[2][k] = tree[1][k * 2] + tree[1][k * 2 + 1]; 44 tree[1][k] = tree[0][k] - tree[3][k] - tree[2][k]; 45 } 46 } 47 else { 48 if (left + 1 == right) 49 tree[3][k] = tree[2][k] = tree[1][k] = 0; 50 else { 51 tree[3][k] = tree[3][k * 2] + tree[3][k * 2 + 1]; 52 tree[2][k] = tree[2][k * 2] + tree[2][k * 2 + 1]; 53 tree[1][k] = tree[1][k * 2] + tree[1][k * 2 + 1]; 54 } 55 } 56 } 57 58 void build(int k, int left, int right) { 59 tree[0][k] = a[right] - a[left]; 60 tree[1][k] = tree[2][k] = tree[3][k] = flag[k] = 0; 61 if (left + 1 != right) { 62 int mid = (left + right) / 2; 63 build(k * 2, left, mid); 64 build(k * 2 + 1, mid, right); 65 } 66 } 67 68 void modify(int k, int left, int right, int l, int r, int v) { 69 if (l <= left && right <= r) { 70 flag[k] += v; 71 pushup(k, left, right); 72 return; 73 } 74 int mid = (left + right) / 2; 75 if (l < mid) 76 modify(k * 2, left, mid, l, r, v); 77 if (r > mid) 78 modify(k * 2 + 1, mid, right, l, r, v); 79 pushup(k, left, right); 80 } 81 82 int main() { 83 int t, cas = 1; 84 scanf("%d", &t); 85 while (t--) { 86 a.clear(), b.clear(), mp.clear(); 87 scanf("%d", &n); 88 // a 记录 y ,b 记录 z 89 for (int i = 0; i < n; i++) { 90 scanf("%d%d%d%d%d%d", &cube[i][0], &cube[i][1], &cube[i][2], &cube[i][3], &cube[i][4], &cube[i][5]); 91 a.push_back(cube[i][1]); 92 a.push_back(cube[i][4]); 93 b.push_back(cube[i][2]); 94 b.push_back(cube[i][5]); 95 } 96 if (n < 3) { 97 printf("Case %d: 0\n", cas++); 98 continue; 99 } 100 sort(a.begin(), a.end()); 101 a.erase(unique(a.begin(), a.end()), a.end()); 102 sort(b.begin(), b.end()); 103 b.erase(unique(b.begin(), b.end()), b.end()); 104 int sz = a.size(), sz2 = b.size(); 105 for (int i = 0; i < sz; i++) 106 mp[a[i]] = i; 107 build(1, 0, sz - 1); 108 long long res = 0; 109 for (int i = 0; i < sz2 - 1; i++) { // 枚举z 110 line.clear(); 111 for (int j = 0; j < n; j++) { 112 if (cube[j][2] <= b[i] && cube[j][5] >= b[i + 1]) { // 找到合法的长方体 113 line.push_back(Line(cube[j][0], cube[j][1], cube[j][4], 1)); 114 line.push_back(Line(cube[j][3], cube[j][1], cube[j][4], -1)); 115 } 116 } 117 sort(line.begin(), line.end()); 118 int sz3 = line.size(); 119 for (int j = 0; j < sz3; j++) { 120 if (j != 0) 121 res += (b[i + 1] - b[i]) * (line[j].lx - line[j - 1].lx) * (long long)tree[3][1]; 122 modify(1, 0, sz - 1, mp[line[j].h1], mp[line[j].h2], line[j].flag); // 和二维的扫描线是一样的 123 } 124 } 125 printf("Case %d: %lld\n", cas++, res); 126 } 127 return 0; 128 }