⭐ Acwing三体攻击
🌹 大佬英明
输入样例
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
⭐ 暴力枚举 (看懂题意就有 83 分了)
import java.io.*;
import java.util.*;
public class Main
{
static int N = 2000010, A, B, C, m;
static int[][][] data;
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException
{
String[] ss = in.readLine().split(" ");
A = Integer.parseInt(ss[0]);
B = Integer.parseInt(ss[1]);
C = Integer.parseInt(ss[2]);
m = Integer.parseInt(ss[3]);
data = new int[A + 1][B + 1][C + 1];
int idx = 0;
ss = in.readLine().split(" ");
for (int i = 1; i <= A; i++)
for (int j = 1; j <= B; j++)
for (int k = 1; k <= C; k++)
data[i][j][k] = Integer.parseInt(ss[idx++]);
int lat, rat, lbt, rbt, lct, rct, ht;
for (int p = 1; p <= m; p++)
{
// 三维坐标 两个点
ss = in.readLine().split(" ");
lat = Integer.parseInt(ss[0]);
rat = Integer.parseInt(ss[1]);
lbt = Integer.parseInt(ss[2]);
rbt = Integer.parseInt(ss[3]);
lct = Integer.parseInt(ss[4]);
rct = Integer.parseInt(ss[5]);
ht = Integer.parseInt(ss[6]);
for (int i = lat; i <= rat; i++)
for (int j = lbt; j <= rbt; j++)
for (int k = lct; k <= rct; k++)
{
data[i][j][k] -= ht;
if (data[i][j][k] < 0)
{
System.out.println(p);
System.exit(0);
}
}
}
}
}
⭐ 三维前缀和
🐷 一言难尽…
🌹 大佬高见
import java.io.*;
import java.util.*;
public class Main
{
static int N = 2000010, A, B, C, m;
static long[] s = new long[N];// 原数组
static long[] b = new long[N];// 差分数组
static long[] bp = new long[N];
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
static int[][] d = { { 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 }, };
static int[][] op = new int[N / 2][7];// 操作数组
static int get(int i, int j, int k)
{
return (i * B + j) * C + k;
}
private static boolean check(int mid)
{
// bp = Arrays.copyOf(b, bp.length);
// b = Arrays.copyOf(bp, bp.length);
for (int i = 0; i < bp.length; i++)
b[i] = bp[i];
// 给 (x1,y1,z1)(x2,y2,z2) 之间加上 c
for (int i = 1; i <= mid; i++)// 做mid次操作
{
int x1 = op[i][0];
int x2 = op[i][1];
int y1 = op[i][2];
int y2 = op[i][3];
int z1 = op[i][4];
int z2 = op[i][5];
int c = -op[i][6];//注意 -1 是消耗的防御
b[get(x1, y1, z1)] += c;
b[get(x1, y1, z2 + 1)] -= c;
b[get(x1, y2 + 1, z1)] -= c;
b[get(x1, y2 + 1, z2 + 1)] += c;
b[get(x2 + 1, y1, z1)] -= c;
b[get(x2 + 1, y2 + 1, z1)] += c;
b[get(x2 + 1, y1, z2 + 1)] += c;
b[get(x2 + 1, y2 + 1, z2 + 1)] -= c;
}
// 根据差分数组求原数组
Arrays.fill(s, 0);
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];
int y = j - d[u][1];
int z = k - d[u][2];
int 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;
}
public static void main(String[] args) throws IOException
{
String[] ss = in.readLine().split(" ");
A = Integer.parseInt(ss[0]);
B = Integer.parseInt(ss[1]);
C = Integer.parseInt(ss[2]);
m = Integer.parseInt(ss[3]);
// 输入数据
ss = in.readLine().split(" ");
int idx = 0;
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)] = Long.parseLong(ss[idx++]);
}
// 根据原数组 s[] 计算差分数组 b
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];
int y = j - d[u][1];
int z = k - d[u][2];
int t = d[u][3];
bp[get(i, j, k)] += s[get(x, y, z)] * t;
}
// 读取操作
for (int i = 1; i <= m; i++)
{
ss = in.readLine().split(" ");
for (int j = 0; j < 7; j++)
op[i][j] = Integer.parseInt(ss[j]);
}
int l = 1;
int r = m;
while (l < r)
{
int mid = l + r >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
System.out.println(r);
}
}