首页 > 其他分享 >798. 差分矩阵

798. 差分矩阵

时间:2023-02-25 11:24:23浏览次数:46  
标签:x1 int 矩阵 差分 798 x2 y1 y2

二维差分模板题
https://www.acwing.com/problem/content/800/
同一维差分一样的思想,重要的也是时刻保证a[i]=b[0]+b[1]+...+b[i]
在二维则是:a[i][j]=b[0][0]+b[0][1]+...b[0][n]+b[1][0]+b[1][2]+..+b[i][j],也就是b的一个小矩阵之和是a[i][j]
要使得一个矩阵内的元素都加上C,二维的差分可以将O(N^2)->O(1)
因为要时刻确保a矩阵是b矩阵的前缀和,所以我们更改b矩阵,就会导致a矩阵的值发生变化(a数组也是b数组所构成的)
因此如果我们在b[x1][y1]上加上c,由于a是由b组成的,那么a[x1][y1]~a[n][n]这个范围的矩阵都会加上c
只要在b[x1[y2+1]上减去c,b[x2+1][y1]上减去c,b[x2+1][y2+1]上加上c,就可以使得a[x2+1][y2+1]~a[n][n]的值不变,这样就满足了题意
关键操作:

b[x1][y1] + = c; b[x1,][y2+1] - = c; b[x2+1][y1] - = c; b[x2+1][y2+1] + = c; 如果看不懂原理的看图即可
还有一点关键的是,如何构造差分矩阵b(满足a是b的前缀和)
由于a是b的前缀和,我们认为a,b初始没有值,那么对b赋与适当的值就能构造出原来的a(只要满足a是前缀和即可)
那么实际上,我们只需要让b[i][j]在(i,j)~(i,j)这个范围上每次+=c(c传入的是a[i][j]),原来a是0,但是由于b[i][j]=c了,那么a[i][j]=0+0+...+c,也就是a[i][j]成为了原来的a[i][j]
但是要满足原来的前缀和性质,如果只是这样操作的话,a[i][j]后面的值都会加上一个c,因此我们需要减的操作
同样的将b[x1][y2+1]减去c,b[x2+1][y1]减去c,这样a[x2+1][y2+1]又多减去了一遍c(因为a[x2+1][y2+1]是由b[x1][y2+1],b[x2+1][y1]等构成的),因此再加上c
b这样操作4步之后,仅仅只有b[x1][y1]满足了前缀和以及恢复原来的a[x1][y1],因此我们需要对所有点这样操作一遍,恢复所有的a[i][j],满足所有的a是b的前缀和
对所有点这样操作4步,每个点都加上了a[i][j],但是周围都减去或加上了c,这样是使得b始终满足差分的性质
那么实际上,这样的操作就是我们的关键差分操作,也就是只对[x1][y1]~[x2][y2]产生影响,对其他范围无影响
这样,我们知道b何处减去c,何处加上c,可以满足a是b的前缀和,具有通用性,即i,j是何数都满足这样的操作

大佬的原话:我们可以先假想a数组为空,那么b数组一开始也为空,但是实际上a数组并不为空
因此我们每次让b数组以(i,j)为左上角到以(i,j)为右下角面积内元素(其实就是一个小方格的面积)去插入 c=a[i][j],等价于原数组a中(i,j) 到(i,j)范围内 加上了 a[i][j] ,因此执行n*m次插入操作,就成功构建了差分b数组.


 

#include<iostream>
using namespace std;
const int N = 1e3+10;
int num[N][N],b[N][N];
int n,m,q;
int x1,y1,x2,y2,c;
void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}
int main()
{
    cin >> n >> m >> q;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin >> num[i][j];
            insert(i,j,i,j,num[i][j]);//构建差分矩阵
        }
    while(q--)
    {
        cin >> x1 >> y1 >> x2 >> y2 >> c;
        //差分原理
        insert(x1,y1,x2,y2,c);
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            //构造前缀和,即构造加过c的矩阵a
            b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
        }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            cout << b[i][j] << " ";
        puts("");
    }
    return 0;
}

 

标签:x1,int,矩阵,差分,798,x2,y1,y2
From: https://www.cnblogs.com/lxl-233/p/17153600.html

相关文章

  • 797. 差分
    https://www.acwing.com/problem/content/799/差分模板题差分就是前缀和的逆运算,重要的时刻确保a[i]=b[0]+b[1]+.....+b[i],这是差分的规定关键是构造b数组,可以在输入数......
  • 将含两列的csv文件生成二维矩阵
    gen_diea=pd.read_csv('../data/ddg_data/diea-gene.csv',header=None,names=['diease','gene'])#生成关联矩阵df=pd.get_dummies(gen_diea.gene).groupby(gen_diea.d......
  • 正交实验与极差分析
    正交试验极差分析流程如下图:正交试验说明正交试验是研究多因素试验的设计方法。对于多因素、多水平的实验要求,如果每个因素的每个水平都要进行试验,这样就会耗费大量的人......
  • 双因素方差分析全流程
    上篇文章讲述了“单因素方差分析全流程总结”,单因素方差分析只是考虑了一个自变量(定类)与一个因变量(定量)之间的关系,但是在实际问题研究中可能研究两个或者几个因素与因变量......
  • 一、基础算法(快排,归并,二分,高精度,前缀和,差分)
    一、基础算法快速排序题目:给定你一个长度为n的整数数列。请你使用快速排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。数据范围:1≤n≤100000,所有......
  • numpy中的矩阵
    numpy中的矩阵1.矩阵矩阵,和array的区别是矩阵必须是2维的,但array可以是多维的2.向量3.加法和标量相乘4.矩阵向量乘法矩阵乘法遵循准则:(M行,N列)*(N行,L列)=(M行,L列)......
  • 【YBT2023寒假Day15 A】破烂衣裳(Burnside引理)(DP)(矩阵乘法)
    破烂衣裳题目链接:YBT2023寒假Day15A题目大意有一个n个点的环,有k种颜色,一开始都没有颜色。每次你可以选择一个位置,把它染成k种颜色的其中一个,但是相邻的两个位置......
  • matlab 矩阵乘法与点乘
    一,*和.*的联系和区别。1,在进行数值运行和数值乘矩阵,这两种没有区别,例如:a*b=a.*b;a*B=a.*B;B*a=B.*a(其中小写字母表示数值,大写字母表示矩阵,下同)。2,在处理矩阵乘......
  • 算法刷题-数组排序(图算法、算法高阶)、螺旋矩阵(数组、矩阵)、分发糖果(贪心、数组)
    数组排序(图算法、算法高阶)编写一个JavaApplication程序,将随机生成的无序数组使用冒泡排序,将这个混乱的数组变成一个从小到大排列的有序的数组并输出。classdemo_sort......
  • 矩阵变换和Matrix4x4
    平移varm=Matrix4x4.Translate(newVector3(10,20,30));Debug.Log($"{m}");  缩放varm=Matrix4x4.Scale(newVector3(1,2,3));Debug.Log($"{m}")......