题目链接: http://acm.whu.edu.cn/land/problem/detail?problem_id=1581
---------------------------------------------------------------------------------------
观察到第一维最大只有$10$ 于是第一维可以直接枚举 $($把长方体切成矩形$)$
观察到第二维最大只有$100$ 于是第二维也可以继续枚举 $($把矩形切成线段$)$
如果最后一维用线段树实现区间覆盖的话 复杂度为
$O(n^{2}kmlog(n * k ^ 2))$ $(n <= 10, k <= 10, m <= 1000)$
由于时限只有$500ms$ 还有多组数据 这样很可能$T$掉
再多想想我们会发现只有区间覆盖操作而没有区间修改操作$($相当于没有回档功能$)$
那就直接维护每个点所在覆盖线段的右端点即可
而维护操作显然是用并查集比较方便
复杂度减少了一个$log$后 单组$10^6$ 多组也不会$T$了
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 int a[11][110][1010], fa[11][110][1010]; 7 int n, k0, m, n2, n3, sum, ans; 8 int p1, q1, r1, p2, q2, r2; 9 int findf(int x, int y, int z) 10 { 11 if(fa[x][y][z] != z) 12 fa[x][y][z] = findf(x, y, fa[x][y][z]); 13 return fa[x][y][z]; 14 } 15 int main() 16 { 17 while(scanf("%d%d%d", &n, &k0, &m) != EOF) 18 { 19 n2 = n * k0; 20 n3= n2 * k0; 21 for(int i = 1; i <= n; ++i) 22 for(int j = 1; j <= n2; ++j) 23 { 24 for(int k = 1; k <= n3; ++k) 25 { 26 scanf("%d", &a[i][j][k]); 27 fa[i][j][k] = k; 28 } 29 fa[i][j][n3 + 1] = n3 + 1; 30 } 31 sum = 0; 32 ans = -1e9; 33 while(m--) 34 { 35 scanf("%d%d%d%d%d%d", &p1, &q1, &r1, &p2, &q2, &r2); 36 for(int i = p1; i <= p2; ++i) 37 for(int j = q1; j <= q2; ++j) 38 for(int k = r1; k <= r2; k = fa[i][j][k]) 39 if(findf(i, j, k) == k) 40 { 41 sum += a[i][j][k]; 42 fa[i][j][k] = findf(i, j, k + 1); 43 } 44 ans = max(ans, sum); 45 } 46 printf("%d ", ans); 47 } 48 return 0; 49 }