首页 > 其他分享 >二维前缀和学习指南

二维前缀和学习指南

时间:2024-08-12 19:50:46浏览次数:10  
标签:学习指南 tsn le 前缀 int sum 矩阵 二维 short

为什么我为OI泪目,因为我菜得离谱......

二维前缀和

引子

二维前缀和,仅仅是由一维前缀和进阶了一维而已。
为了方便后面的学习,我先给出二维前缀和重点代码。

处理二维前缀和
for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
		sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
查询二维前缀和
int a1,b1,a2,b2;//待查询的点A(a1,b1)左上角 B(a2,b2)右下角
int ans=sum[a2][b2]-sum[a2][b1-1]-sum[a1-1][b2]+sum[a1-1][b1-1];//ans:答案

接下来以例题举例。

例题

最大加权矩形

题目描述

为了更好的备战 NOIP2013,电脑组的几个女孩子 LYQ,ZSC,ZHQ 认为,我们不光需要机房,我们还需要运动,于是就决定找校长申请一块电脑组的课余运动场地,听说她们都是电脑组的高手,校长没有马上答应他们,而是先给她们出了一道数学题,并且告诉她们:你们能获得的运动场地的面积就是你们能找到的这个最大的数字。

校长先给他们一个 \(n\times n\) 矩阵。要求矩阵中最大加权矩形,即矩阵的每一个元素都有一权值,权值定义在整数集上。从中找一矩形,矩形大小无限制,是其中包含的所有元素的和最大 。矩阵的每个元素属于 \([-127,127]\) ,例如

 0 –2 –7  0 
 9  2 –6  2
-4  1 –4  1 
-1  8  0 –2

在左下角:

9  2
-4  1
-1  8

和为 \(15\)。

几个女孩子有点犯难了,于是就找到了电脑组精打细算的 HZH,TZY 小朋友帮忙计算,但是遗憾的是他们的答案都不一样,涉及土地的事情我们可不能含糊,你能帮忙计算出校长所给的矩形中加权和最大的矩形吗?

输入格式

第一行:\(n\),接下来是 \(n\) 行 \(n\) 列的矩阵。

输出格式

最大矩形(子矩阵)的和。

样例 #1

样例输入 #1
4
0 -2 -7 0
 9 2 -6 2
-4 1 -4  1 
-1 8  0 -2
样例输出 #1
15

提示

\(1 \leq n\le 120\)

分析

看一下数据,\(n<=120\),乍看挺小,但直接暴力是\(O(n^6)\),直接爆掉。
所以要另外寻找做法。

Step1

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
我们令sum[i][j]:从(1,1)到(i,j)的矩阵和,我们就能发现蓝色部分
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
为红色部分
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
加上绿色部分
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
减去紫色部分
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
最后再加上\(a_i,_j\)这个点
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
所以Get代码

for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
		sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];

sum[i-1][j],sum[i][j-1],sum[i-1][j-1],a[i][j]都是已知的,所以不用担心。

Step2

再看查询
比如我们要查询(2,2)~(3,3)这个矩阵内的和
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其实就相当于
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
减去
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
再减去
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
最后根据容斥原理,在紫色点上连减两次,需要补回这个矩阵
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
所以GET代码(这里要枚举左上点和右下点坐标)

for(int x_1=1;x_1<=n;x_1++)
        for(int y_1=1;y_1<=n;y_1++)
            for(int x_2=x_1;x_2<=n;x_2++)
                for(int y_2=y_1;y_2<=n;y_2++)
                    lans=max(lans,sum[x_2][y_2]-sum[x_1-1][y_2]-sum[x_2][y_1-1]+sum[x_1-1][y_1-1]);

提示:珍爱生命,远离y0,y1.

CODE

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int tsn=120+5;

int n;
int lans=INT_MIN;
int a[tsn][tsn];
int qz[tsn][tsn];
int sum[tsn][tsn];
signed main()
{
    #ifndef ONLINE_JUDGE
        freopen("00in.txt","r",stdin);
        freopen("00out.txt","w",stdout);
    #endif
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>a[i][j];
            qz[i][j]=qz[i][j-1]+a[i][j];
            sum[i][j]=qz[i][j]+sum[i-1][j];
        }
    for(int x_1=1;x_1<=n;x_1++)
        for(int y_1=1;y_1<=n;y_1++)
            for(int x_2=x_1;x_2<=n;x_2++)
                for(int y_2=y_1;y_2<=n;y_2++)
                    lans=max(lans,sum[x_2][y_2]-sum[x_1-1][y_2]-sum[x_2][y_1-1]+sum[x_1-1][y_1-1]);
    cout<<lans;
    return 0;
}


[HNOI2003] 激光炸弹

题目描述

一种新型的激光炸弹,可以摧毁一个边长为 \(m\) 的正方形内的所有目标。现在地图上有 \(n\) 个目标,用整数 \(x_i\) , \(y_i\) 表示目标在地图上的位置,每个目标都有一个价值 \(v_i\)。激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为 \(m\) 的边必须与 \(x\) 轴,\(y\) 轴平行。若目标位于爆破正方形的边上,该目标不会被摧毁。

现在你的任务是计算一颗炸弹最多能炸掉地图上总价值为多少的目标。

可能存在多个目标在同一位置上的情况。

输入格式

输入的第一行为整数 \(n\) 和整数 \(m\);

接下来的 \(n\) 行,每行有 \(3\) 个整数 \(x, y, v\),表示一个目标的坐标与价值。

输出格式

输出仅有一个正整数,表示一颗炸弹最多能炸掉地图上总价值为多少的目标(结果不会超过 \(32767\) )。

样例 #1

样例输入 #1
2 1
0 0 1
1 1 1
样例输出 #1
1

提示

数据规模与约定

  • 对于 \(100\%\) 的数据,保证 \(1 \le n \le 10^4\),\(0 \le x_i ,y_i \le 5\times 10^3\),\(1 \le m \le 5\times 10^3\),\(1 \le v_i < 100\)。

分析

点我

CODE (only 91分,死调不过,仅供参考)

#include<bits/stdc++.h>
using namespace std;
const short tsn=5e3+5;

short n,m;
short maxx=0,maxy=0;
short lans=-1314;
short a[tsn][tsn];
short qz[tsn][tsn];
int sum[tsn][tsn];
signed main()
{
    #ifndef ONLINE_JUDGE
        freopen("00in.txt","r",stdin);
        freopen("00out.txt","w",stdout);
    #endif
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

    cin>>n>>m;//what can I say?
    for(short i=1,x,y,v;i<=n;i++)
    {
        cin>>x>>y>>v;x++,y++;
        a[x][y]+=v;
        maxx=max(int(x),int(maxx)),maxy=max(int(y),int(maxy));
    }
    for(short i=1;i<=maxx;i++)
        for(short j=1;j<=maxy;j++)
        {
            qz[i][j]=qz[i][j-1]+a[i][j];
            sum[i][j]=sum[i-1][j]+qz[i][j];
        }
    for(short a1=m;a1<=maxx;a1++)
        for(short b1=m;b1<=maxy;b1++)
        {
            lans=max(int(lans),int(sum[a1][b1]-sum[a1-m][b1]-sum[a1][b1-m]+sum[a1-m][b1-m]));
        }
    cout<<lans;
    return 0;
}


完结撒花


在这里插入图片描述
图片来自网络。

标签:学习指南,tsn,le,前缀,int,sum,矩阵,二维,short
From: https://www.cnblogs.com/happy-salted-fish/p/18355613

相关文章

  • 练习讲解--手动为二维数组的每个元素赋值
    importjava.util.*;publicclassA{publicstaticvoidmain(String[]args){Scannerinput=newScanner(System.in);int[][]nums=newint[3][4];for(inti=0;i<nums.length;i++){for(intj=0;j<nums[i].lengt......
  • 第七章 二维数组
    文章目录第七章二维数组1.冒泡排序2.使用Arrays为数组排序3.二维数组第七章二维数组1.冒泡排序每次比较相邻两数小的交换到前面每轮结束后最大的数交换到最后5个数字如何存放数组,数组.length=5控制比较多少轮外层循环,循环变量i控制每轮比较多少次内......
  • 【408DS算法题】009进阶-二维数组的查找
    Index题目实现代码分析题目在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。​进阶要求——时间复杂度:......
  • BUUCTF 81题吹着贝斯的二维码详解(包含各类工具和python脚本)
    在网上看了很多类似解题步骤和说明,感觉对小白都不友好,于是决定搜集整理下,做个详尽的解题步骤:压缩包解压得到36个无后缀名文件和一个flag.zip压缩包再看压缩包,解压发现有压缩密码,用winhex查看是不是伪加密,在末尾发现一串可疑字符串,拷贝下来留用:GNATOMJVIQZUKNJXGRCTGNRTG......
  • 初始化二维vector
    这里是我遇到的一些对于二维vector容器初始化的一些问题的总结与记录,一共有一下四种情况,随时添加新的方式方法。初始化一个二维vector,行M,列N//初始化一个二维的matrix,行M,列N,且值为0vector<vector<int>>matrix(M,vector<int>(N));//等价于下面的vector<vector<......
  • Java | 图片地址查询返回参数自动拼接图片前缀地址
    代码介绍自定义的JsonSerializer来处理图片URL的拼接,增加了灵活性和可配置性。关键点:自动拼接域名:通过properties.getEndpoint()从配置文件中获取Minio接口域名,然后根据条件决定是否拼接域名。处理多个图片URL:代码处理了可能包含多个图片URL的情况(以逗号分隔),并且确保了每个UR......
  • 编写类 MyTools 类,编写一个方法可以打印二维数组的数据。 2) 编写一个方法 copyPerson
    1publicclassMethodExercise02{2publicstaticvoidmain(String[]args){34Personp=newPerson();5p.name="milan";6p.age=100;7//创建tools8MyToolstools=newMyTools();9......
  • java 生成 二维码
    ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。导入对应的jar包<dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <v......
  • 第四章 前缀和,差分
    目录1前缀和1.1什么是前缀和?1.2前缀和的作用注意事项:1.3一维前缀和1.3.1代码模板1.3.2例题分析:  代码:1.4二维前缀和 1.4.1代码模板2差分2.1什么是差分?2.2差分的作用注意事项: 2.3一维差分2.3.1代码模板 2.4二维差分2.4.1代码模板3前缀......
  • 前缀和 & 差分
    1.前缀和前缀和是一种支持不带修改,多次查询的数据结构。1.1一维前缀和维护前缀和数组\(b_i=\sum\limits_{j=1}^ia_i\),则\(b\)数组还可以通过递推式\(b_i=b_{i-1}+a_i\)得到。当需要求区间\([l,r]\)的和,就可以通过\(b\)数组\(b_r-b_{l-1}\)得到,时间复杂度\(\mat......