三维(差分+前缀和)应用

Description:三体攻击

三体人将对地球发起攻击。
为了抵御攻击,地球人派出了 A × B × C 艘战舰,在太空中排成一个 A 层 B 行 C 列的立方体。其中,第i 层第 j 行第 k 列的战舰(记为战舰 (i, j, k))的生命值为 d(i, j, k)。三体人将会对地球发起 m 轮“立方体攻击”,每次攻击会对一个小立方体中的所有战舰都造成相同的伤害。
具体地,第 t 轮攻击用 7 个参数lat, rat, lbt, rbt, lct, rct, ht 描述;所有满足
i ∈ [lat, rat],j ∈ [lbt, rbt],k ∈ [lct, rct] 的战舰 (i, j, k) 会受到 ht的伤害。
如果一个战舰累计受到的总伤害超过其防御力,那么这个战舰会爆炸。
地球指挥官希望你能告诉他,第一艘爆炸的战舰是在哪一轮攻击后爆炸的。

思路1:暴力求解

暴力求解的方法是依次进行每一轮攻击,然后更新攻击范围内的战舰的生命值,当第t轮某一个战舰的血量小于0,那么直接返回 t.

思路2:二分+差分+前缀和

利用二分,第一次连续攻击m/2轮,然后判断战舰的生命值,如果此时没有战舰爆炸,那么再往后攻击m/4轮;如果此时有战舰爆炸,那么往前恢复m/4轮。不断二分,直到找到是在第几轮攻击时导致战舰爆炸。
那么怎么实现连续攻击m/2轮?
利用差分数组,再求前缀和

一、前缀和的概念:

例如,给出一组数 arr[ 1 , 2 , 3 , 4 , 5 ]
其前缀和 Sn[ 1, 3 , 6 , 10 , 15 ]
即 Sn[i] = Sn[i-1] + arr[i];

二、前缀和的特点:

  1. O(N)的时间维护
    例如,arr[2] += 3;
    则Sn[ 1, 3 , 6+3 , 10+3 , 15+3 ]
  2. O(1)的时间获取区间和
    例如,求在 [2,4] 的区间内数值和
    即 Sn[4] - Sn[1] = 15 - 3 = 12

三、一维差分数组+前缀和:

在这里插入图片描述

四、二维差分数组+前缀和:
在这里插入图片描述
五、三维差分数组+前缀和:

1、三维差分数组
在这里插入图片描述
给定三个角的坐标la , ra , lb , rb , lc , rc和攻击力h
正面四个
arr[lc][lb][la] += h;
arr[rc+1][lb][la] -= h;
arr[lc][lb][ra+1] -= h;
arr[rc+1][lb][ra+1] += h;
左面补两个
arr[lc][rb+1][la] -= h;
arr[lc][rb+1][ra+1] += h;
上面再补两个
arr[rc+1][rb+1][la] += h;
arr[rc+1][rb+1][ra+1] -= h;
2、三维前缀和
在这里插入图片描述
画的很乱,建议各位自己试着画一画。
arr[i][j][k] += arr[i][j-1][k]; //后方
arr[i][j][k] += arr[i-1][j][k];//左侧
arr[i][j][k] += arr[i][j][k-1]; //下方
arr[i][j][k] -= arr[i-1][j-1][k]; //左后
arr[i][j][k] -= arr[i-1][j][k-1]; //左下
arr[i][j][k] -= arr[i][j-1][k-1]; //后下
arr[i][j][k] += arr[i-1][j-1][k-1]; //左后下

六、算法实现

  1. 暴力求解
    private static int[] arr;
    private static int[][] attacks;
    private static int A,B,C,m;
    public static void main(String[] args) {
   
        Scanner cin = new Scanner(System.in);
        A = cin.nextInt();
        B = cin.nextInt();
        C = cin.nextInt();
        m = cin.nextInt();
        arr = new int[(A+1)*(B+1)*(C+1)];
        attacks = new int[m+1][7];
        //初始化战舰生命值
        for (int i = 1;i < A+1;i++){
   
            for (int j = 1;j < B+1;j++){
   
                for (int k = 1;k < C+1;k++){
   
                    arr[getIndex(i,j,k)] = cin.nextInt();
                }
            }
        }

        //执行攻击
        for (int k = 1; k < m+1; k++) {
   
            for (int m = 0;m < 7;m++) //读入攻击信息。
                attacks[k][m] = cin.nextInt();

            for (int i = attac
<think>好的,我现在需要回答用户关于二维差分前缀和的问题。首先,我得回忆一下相关知识,确保自己理解正确。 首先,二维前缀和,应该是一个数组,每个元素代表从左上角(0,0)到当前位置的所有元素之和。计算方法的话,记得可能有递推公式,比如sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + 当前元素。因为如果不减去sum[i-1][j-1],就会重复计算那个区域。用户提供的引用里提到sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1],可能这里原数组已经存储了初始值,然后逐步累加前缀和。需要确认正确的计算步骤。 然后是二维差分差分通常是前缀和的逆操作。一维差分中,差分数组的构造是通过原数组相邻元素的差,而二维差分可能需要处理二维区域的变化。例如,要在某个矩形区域内加上一个值,通过差分数组可以高效实现,而不需要逐个元素修改。构造二维差分数组的方法可能涉及在特定四个角点进行加减操作,比如在(x1,y1)处加v,在(x2+1,y1)减v,在(x1,y2+1)减v,在(x2+1,y2+1)加v,这样在计算前缀和的时候,这个区域就会被正确加上v。需要确认这个步骤是否正确。 应用场景方面,二维前缀和适用于快速查询子矩阵的和,这在图像处理、动态规划或者需要频繁求子矩阵和的场景下很有用。二维差分则适用于对子矩阵进行多次增减操作后,快速得到最终矩阵的情况,比如图像编辑中的区域亮度调整,或者游戏中的地图更新等。 接下来,根据用户提供的引用,尤其是引用[4],里面提到了二维前缀和的计算方法,以及如何查询子矩阵的和。这可以作为参考,确保我的回答与引用内容一致。例如,计算子矩阵和的公式是sum[c][d] - sum[c][b-1] - sum[a-1][d] + sum[a-1][b-1],这需要确认是否正确,是否在用户提供的引用中有正确描述。 另外,用户提到的补第0行和第0列,可能是为了处理边界情况,避免复杂的条件判断。例如,如果数组从1开始索引,那么0行和0列可以初始化为0,这样在计算时不需要处理i-1或j-1为负数的情况。 现在,需要将二维差分前缀和的计算方法分步骤解释清楚,可能包括构造前缀和数组、查询子矩阵和、构造差分数组以及应用增量操作的方法。同时,应用场景需要结合引用中的内容,比如多次查询区间和时前缀和的高效性,差分在处理范围更新时的优势。 还要注意用户提到的LaTeX格式要求,所有数学表达式要用$...$或$$...$$,并且正确使用中文回答。同时生成相关问题,可能需要涉及实现步骤、应用实例、优化方法等。 最后,确保回答的结构清晰,先讲二维前缀和,再讲二维差分,分别包括定义、计算方法、应用场景,最后给出相关问题。检查是否有遗漏或错误,比如是否正确引用用户提供的参考资料,例如引用[4]提到的内容。</think>### 二维差分前缀和详解 #### 一、二维前缀和 **定义** 二维前缀和指矩阵中某个位置 $(i,j)$ 左上角所有元素的和。通过预处理生成前缀和数组,可以快速计算任意子矩阵的和。 **计算方法** 1. **构造前缀和数组**: 设原矩阵为 $arr$,前缀和矩阵为 $sum$,则递推公式为: $$sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + arr[i][j]$$ 通常补第0行和第0列(初始化为0),避免边界判断[^4]。 2. **查询子矩阵和**: 若查询左上角 $(a,b)$ 到右下角 $(c,d)$ 的和,公式为: $$sum[c][d] - sum[c][b-1] - sum[a-1][d] + sum[a-1][b-1]$$ 这一过程的时间复杂度为 $O(1)$[^3]。 **应用场景** - 图像处理中快速计算区域像素和 - 动态规划中优化子矩阵统计问题 - 多次查询矩阵区间和的场景(如数据统计) --- #### 二、二维差分 **定义** 二维差分前缀和的逆操作,用于高效处理矩阵中某子矩阵的数值增减操作。 **计算方法** 1. **构造差分数组**: 差分数组 $diff$ 满足: $$arr[i][j] = \sum_{x=0}^{i} \sum_{y=0}^{j} diff[x][y]$$ 2. **范围增减操作**: 若要在左上角 $(x1,y1)$ 到右下角 $(x2,y2)$ 的子矩阵中增减值 $v$,操作差分数组的四个点: ```text diff[x1][y1] += v diff[x2+1][y1] -= v diff[x1][y2+1] -= v diff[x2+1][y2+1] += v ``` 3. **还原原矩阵**: 对差分数组做二维前缀和即可得到修改后的原矩阵。 **应用场景** - 图像处理中对某区域统一调整亮度 - 游戏地图中批量更新地形数值 - 多次范围修改后快速生成最终矩阵的场景[^2] --- #### 三、实例说明 **前缀和示例** 原矩阵: $$\begin{bmatrix}1 & 2 \\ 3 & 4\end{bmatrix}$$ 前缀和矩阵(补0行0列后): $$\begin{bmatrix}0 & 0 & 0 \\ 0 & 1 & 3 \\ 0 & 4 & 10\end{bmatrix}$$ 查询 $(1,1)$ 到 $(2,2)$ 的和:$10 - 3 - 4 + 0 = 3$[^4]。 **差分示例** 若对左上角 $(1,1)$ 到 $(2,2)$ 加2,差分数组操作后还原,原矩阵变为: $$\begin{bmatrix}1 & 2 \\ 3 & 6\end{bmatrix}$$ ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值