solution.md 4.6 KB
Newer Older
每日一练社区's avatar
每日一练社区 已提交
1 2 3 4 5 6 7 8
# 三体攻击


**题目描述**

三体人将对地球发起攻击。为了抵御攻击,地球人派出了 A × B × C 艘战舰,在太空中排成一个 A 层 B 行 C 列的立方体。其中,第 i 层第 j 行第 k 列的战舰(记为战舰 (i, j, k))的生命值为 d(i, j, k)。

三体人将会对地球发起 m 轮“立方体攻击”,每次攻击会对一个小立方体中的所有战舰都造成相同的伤害。具体地,第 t 轮攻击用 7 个参数 $la_t, ra_t, lb_t, rb_t, lc_t, rc_t, h_t $描述;
每日一练社区's avatar
每日一练社区 已提交
9

每日一练社区's avatar
每日一练社区 已提交
10 11 12 13 14 15 16 17
所有满足$ i ∈ [la_t, ra_t],j ∈ [lb_t, rb_t],k ∈ [lc_t, rc_t] $的战舰 (i, j, k) 会受到 $h_t$ 的伤害。如果一个战舰累计受到的总伤害超过其防御力,那么这个战舰会爆炸。

地球指挥官希望你能告诉他,第一艘爆炸的战舰是在哪一轮攻击后爆炸的。


**输入格式**

从标准输入读入数据。
每日一练社区's avatar
每日一练社区 已提交
18

每日一练社区's avatar
每日一练社区 已提交
19
第一行包括 4 个正整数 A, B, C, m;  
每日一练社区's avatar
每日一练社区 已提交
20

每日一练社区's avatar
每日一练社区 已提交
21
第二行包含 A × B × C 个整数,其中第 ((i − 1)×B + (j − 1)) × C + (k − 1)+1 个数为 d(i, j, k);  
每日一练社区's avatar
每日一练社区 已提交
22

每日一练社区's avatar
每日一练社区 已提交
23 24 25 26 27 28
第 3 到第 m + 2 行中,第 (t − 2) 行包含 7 个正整数 $la_t, ra_t, lb_t, rb_t, lc_t, rc_t, h_t$。


**输出格式**

输出到标准输出。
每日一练社区's avatar
每日一练社区 已提交
29

每日一练社区's avatar
每日一练社区 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
输出第一个爆炸的战舰是在哪一轮攻击后爆炸的。保证一定存在这样的战舰。


**样例输入**

```
2 2 2 3
1 1 1 1 1 1 1 1
1 2 1 2 1 1 1
1 1 1 2 1 2 1
1 1 1 1 1 1 2
```

**样例输出**

```
2
```

**样例解释**

在第 2 轮攻击后,战舰 (1,1,1) 总共受到了 2 点伤害,超出其防御力导致爆炸。


**数据约定**

```
对于 10% 的数据,B = C = 1;
对于 20% 的数据,C = 1;
对于 40% 的数据,A × B × C, m ≤ 10, 000;
对于 70% 的数据,A, B, C ≤ 200;
对于所有数据,A × B × C ≤ 10^6, m ≤ 10^6, 0 ≤ d(i, j, k), ht ≤ 10^9。
```

以下程序实现了这一功能,请你补全空白处的内容:

每日一练社区's avatar
每日一练社区 已提交
66
```c
每日一练社区's avatar
每日一练社区 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
#include <bits/stdc++.h>
using namespace std;

const int N = 2000010;

typedef long long LL;
int A, B, C, m;
LL s[N], b[N], bp[N];
int op[N / 2][7];

const int d[8][4] = {
    {0, 0, 0, 1},
    {0, 0, 1, -1},
    {0, 1, 0, -1},
    {0, 1, 1, 1},
    {1, 0, 0, -1},
    {1, 0, 1, 1},
    {1, 1, 0, 1},
    {1, 1, 1, -1}};

int get(int i, int j, int k)
{

    return (i * B + j) * C + k;
}

bool check(int mid)
{
    memcpy(b, bp, sizeof bp);
    for (int i = 1; i <= mid; i++)
    {
        int x1 = op[i][0], x2 = op[i][1], y1 = op[i][2], y2 = op[i][3], z1 = op[i][4], z2 = op[i][5], h = op[i][6];
        b[get(x1, y1, z1)] -= h;
        b[get(x1, y1, z2 + 1)] += h;
        b[get(x1, y2 + 1, z1)] += h;
        b[get(x1, y2 + 1, z2 + 1)] -= h;
        b[get(x2 + 1, y1, z1)] += h;
        b[get(x2 + 1, y1, z2 + 1)] -= h;
        b[get(x2 + 1, y2 + 1, z1)] -= h;
        b[get(x2 + 1, y2 + 1, z2 + 1)] += h;
    }

    memset(s, 0, sizeof s);
    for (int i = 1; i <= A; i++)
        for (int j = 1; j <= B; j++)
            for (int k = 1; k <= C; k++)
            {
                s[get(i, j, k)] = b[get(i, j, k)];
                for (int u = 1; u < 8; u++)
                {
                    int x = i - d[u][0], y = j - d[u][1], z = k - d[u][2], t = d[u][3];
                    s[get(i, j, k)] -= s[get(x, y, z)] * t;
                }

                if (s[get(i, j, k)] < 0)
                    return true;
            }

    return false;
}

int main()
{
    scanf("%d%d%d%d", &A, &B, &C, &m);

    for (int i = 1; i <= A; i++)
        for (int j = 1; j <= B; j++)
            for (int k = 1; k <= C; k++)
                scanf("%lld", &s[get(i, j, k)]);

    for (int i = 1; i <= A; i++)
        for (int j = 1; j <= B; j++)
            for (int k = 1; k <= C; k++)
                for (int u = 0; u < 8; u++)
                {
                    int x = i - d[u][0], y = j - d[u][1], z = k - d[u][2], t = d[u][3];
                    __________________
                }

    for (int i = 1; i <= m; i++)
        for (int j = 0; j < 7; j++)
            scanf("%d", &op[i][j]);

    int l = 1, r = m;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid))
            r = mid;
        else
            l = mid + 1;
    }

    printf("%d\n", r);
    return 0;
}
```

## 答案

每日一练社区's avatar
每日一练社区 已提交
167
```c
每日一练社区's avatar
每日一练社区 已提交
168 169 170 171 172 173 174
bp[get(i, j, k)] += s[get(x, y, z)] * t;
```

## 选项

### A

每日一练社区's avatar
每日一练社区 已提交
175
```c
每日一练社区's avatar
每日一练社区 已提交
176 177 178 179 180
bp[get(i, j, k)] = s[get(x, y, z)] * t;
```

### B

每日一练社区's avatar
每日一练社区 已提交
181
```c
每日一练社区's avatar
每日一练社区 已提交
182 183 184 185 186
bp[get(i, j, k)] *= s[get(x, y, z)] * t;
```

### C

每日一练社区's avatar
每日一练社区 已提交
187
```c
每日一练社区's avatar
每日一练社区 已提交
188 189
bp[get(i, j, k)] = s[get(x, y, z)] + t;
```