• 差分详解(附加模板和例题)


    一、一维差分

    1.一维差分运用

    设a[N]为原数组,b[N]为差分数组,c[N]为进行操作后得到的新数组

    (1).先求出差分数组b[N]

    1. for(i=1;i<=n;i++)
    2. {
    3. cin>>a[i];
    4. b[i]=a[i]-a[i-1];
    5. }

    (2).进行差分操作,利用void insert(int l,int r,int  c)函数

    1. void insert(int l,int r,int x)
    2. {
    3. b[l]+=x;
    4. b[r+1]-=x;
    5. }

    (3).利用一维前缀和求出新数组c[N]

    1. for(i=1;i<=n;i++)
    2. {
    3. c[i]=c[i-1]+b[i];
    4. }

    2.一维差分相关例题和代码

    输入:

    1. 6 3
    2. 1 2 2 1 2 1
    3. 1 3 1
    4. 3 5 1
    5. 1 6 1

    输出:

    3 4 5 3 4 2

    1.模拟过程

    一维差分:
    a[i]为原数组,b[i]为差分数组 ,c[i]为经过操作后得到的新数组 
    b[i]=a[i]-a[i-1];//a[i]为b[i]的前缀和,即b[i]是a[i]的差分数组 
    c[i]=c[i-1]+b[i];//c[i]为b[i]的前缀和 

    a[i] 1 2 2  1 2  1
    b[i] 1 1 0 -1 1 -1 
    进行以下操作:
    1 3 1
    3 5 1
    1 6 1

    b[1]=b[1]+1=2
    b[3+1]=-1-1=-2;
    2 1 0 -2 1 -1
    b[3]=0+1=1;
    b[5+1]=-1-1=-2;
    2 1 1 -2 1 -2
    b[1]=2+1=3;
    b[6+1]=0-1=-1
    3 1 1 -2 1 -2
    c[i] 3 4 5 3 4 2 

    2.代码

    1. #include
    2. using namespace std;
    3. const int N=1e5+100;
    4. int a[N],b[N],c[N];
    5. void insert(int l,int r,int x)
    6. {
    7. b[l]+=x;
    8. b[r+1]-=x;
    9. }
    10. int main()
    11. {
    12. int n,m;
    13. cin>>n>>m;
    14. int i,j;
    15. for(i=1;i<=n;i++)
    16. {
    17. cin>>a[i];
    18. b[i]=a[i]-a[i-1];
    19. }
    20. while(m--)
    21. {
    22. int l,r,x;
    23. cin>>l>>r>>x;
    24. insert(l,r,x);
    25. }
    26. for(i=1;i<=n;i++)
    27. {
    28. c[i]=c[i-1]+b[i];
    29. cout<' ';
    30. }
    31. cout<
    32. return 0;
    33. }

    二、二维差分

    1.二维差分推导

    1. void insert(int x1,int y1,int x2,int y2,int c)
    2. {
    3. b[x1][y1]+=c;
    4. b[x2+1][y1]-=c;
    5. b[x1][y2+1]-=c;
    6. b[x2+1][y2+1]+=c;
    7. }

    2.二维差分运用

    1.先输入原数组a[N]

    1. for(i=1;i<=n;i++)
    2. {
    3. for(j=1;j<=m;j++)
    4. {
    5. cin>>a[i][j];
    6. }
    7. }

    2.将原数组a[N]中的每个数字,插入到空矩阵b[N]数组中(相当于插入了一个1*1矩阵)

    1. for(i=1;i<=n;i++)
    2. {
    3. for(j=1;j<=m;j++)
    4. {
    5. insert(i,j,i,j,a[i][j]);
    6. }
    7. }

    3.再将左上角(x1,y1),右上角(x2,y2)以及c,插入到insert()函数里面

    1. void insert(int x1,int y1,int x2,int y2,int c)
    2. {
    3. b[x1][y1]+=c;
    4. b[x2+1][y1]-=c;
    5. b[x1][y2+1]-=c;
    6. b[x2+1][y2+1]+=c;
    7. }

    4.利用二维前缀和得到经过操作后的新数组c[N][N] 

    1. for(i=1;i<=n;i++)//二维前缀和
    2. {
    3. for(j=1;j<=m;j++)
    4. {
    5. c[i][j]=c[i-1][j]+c[i][j-1]-c[i-1][j-1]+b[i][j];
    6. }
    7. }

     3.相关例题

    一、题目要求

    输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c其中 (x1,y1)和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。

    每个操作都要将选中的子矩阵中的每个元素的值加上 c。

    请你将进行完所有操作后的矩阵输出。

    输入格式

    第一行包含整数 n,m,q。

    接下来 n 行,每行包含 m 个整数,表示整数矩阵。

    接下来 q 行,每行包含 个整数 x1,y1,x2,y2,c表示一个操作。

    输出格式

    共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

    数据范围

    1≤n,m≤1000
    1≤q≤100000
    1≤x1≤x2≤n
    1≤y1≤y2≤m
    −1000≤c≤1000
    −1000≤矩阵内元素的值≤1000

    输入样例:
    1. 3 4 3
    2. 1 2 2 1
    3. 3 2 2 1
    4. 1 1 1 1
    5. 1 1 2 2 1
    6. 1 3 2 3 2
    7. 3 1 3 4 1
    输出样例:
    1. 2 3 4 1
    2. 4 3 4 1
    3. 2 2 2 2

    二、代码

    1. //二维差分矩阵
    2. #include
    3. #define endl '\n'
    4. #define int long long
    5. #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    6. using namespace std;
    7. const int N=1100;
    8. const int inf=0x3f3f3f3f;
    9. int a[N][N],b[N][N],c[N][N];
    10. int n,m,q;
    11. void insert(int x1,int y1,int x2,int y2,int c)
    12. {
    13. b[x1][y1]+=c;
    14. b[x2+1][y1]-=c;
    15. b[x1][y2+1]-=c;
    16. b[x2+1][y2+1]+=c;
    17. }
    18. void solve()
    19. {
    20. cin>>n>>m>>q;
    21. int i,j;
    22. for(i=1;i<=n;i++)
    23. {
    24. for(j=1;j<=m;j++)
    25. {
    26. cin>>a[i][j];
    27. }
    28. }
    29. //将a矩阵中的每个数插到空矩阵里面去
    30. //进行n*m次插入操作,即将每次插入的数看成1*1的矩阵
    31. for(i=1;i<=n;i++)
    32. {
    33. for(j=1;j<=m;j++)
    34. {
    35. insert(i,j,i,j,a[i][j]);
    36. }
    37. }
    38. while(q--)//得到差分矩阵
    39. {
    40. int x1,x2,y1,y2,c;
    41. cin>>x1>>y1>>x2>>y2>>c;
    42. insert(x1,y1,x2,y2,c);
    43. }
    44. for(i=1;i<=n;i++)//前缀和
    45. {
    46. for(j=1;j<=m;j++)
    47. {
    48. c[i][j]=c[i-1][j]+c[i][j-1]-c[i-1][j-1]+b[i][j];
    49. }
    50. }
    51. for(i=1;i<=n;i++)//输出经过操作后的矩阵
    52. {
    53. for(j=1;j<=m;j++)
    54. {
    55. cout<' ';
    56. }
    57. cout<
    58. }
    59. }
    60. signed main()
    61. {
    62. int t=1;
    63. while(t--)
    64. {
    65. solve();
    66. }
    67. return 0;
    68. }


     

  • 相关阅读:
    《JavaSE-第十七章》之LinkedList
    网络流问题
    【亲测有效】hadoop hive1,hive2 索引加速查询 hive sql优化 大幅优化查询速度 索引建立
    会议文字记录工具【钉钉闪记】
    【读书笔记】《大数据之路》——维度设计总结(3)
    字符函数、字符串函数和内存函数
    注册域名,购买阿里云服务器,备案,域名解析图文教程简介
    4.2 配置Mysql与注册登录模块(中)
    C++ 里面lambda和函数指针的转换
    关于Flask高级_WTF自定义验证器的方法
  • 原文地址:https://blog.csdn.net/m0_73557680/article/details/134450076