whu 1581 Union of cubes

题目链接: 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\n", ans);
47     }
48     return 0;
49 }

 

posted @ 2016-04-12 20:26  sagitta  阅读(203)  评论(1编辑  收藏  举报