• 一维和二维差分


    前缀和的逆运算

    一维差分

    a1,a2,a3……an  //前缀和数组

    构造b1,b2,b3……bn    b数组是a数组的差分

    使得ai=b1+b2+……+bi

    故b1=a1;

    b2=a2-a1;

    b3=a3-a2

    bn=an-a(n-1)

    当然,实际构造中不需要特意构造b,具体操作参考代码部分

    可认为a数组初始全为0,然后进行[1,1]+a1,[2,2]+a2,[3,3]+a3……[n,n]+an的借助b数组的插入操作

    作用:当需要希望a数组[l,r]全部加c时,时间复杂度为O(n);

              可使bl+c,b(r+1)-c达到同样效果,时间复杂度为O(1);

    输入一个长度为 n 的整数序列。

    接下来输入 m个操作,每个操作包含三个整数 l,r,c表示将序列中 [l,r] 之间的每个数加上 c。

    请你输出进行完所有操作后的序列。

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

    二维差分

    现在需令阴影部分全部+c,则

    b(x1,y1)+=c;(蓝色框所选a+=c)

    b(x2+1,y1)-=c(紫色框a-=c)

    b(x1,y2+1)-=c(红色框a-=c)

    b(x2+1,y2+1)+=c(红紫公共区域a+=c)

    b的构造思路与一维差分类似

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

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

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

    1. #include
    2. #include
    3. using namespace std;
    4. const int N = 1010;
    5. int a[N][N];
    6. int b[N][N];
    7. void insert(int x1, int y1, int x2, int y2,int c)
    8. {
    9. b[x1][y1] += c;
    10. b[x2 + 1][y1] -= c;
    11. b[x1][y2 + 1] -= c;
    12. b[x2 + 1][y2 + 1] += c;
    13. }
    14. int main()
    15. {
    16. int n, m, q;
    17. cin >> n >> m >> q;
    18. for (int i = 1; i <= n; i++)
    19. {
    20. for (int j = 1; j <= m; j++)
    21. {
    22. cin >> a[i][j];
    23. insert(i, j, i, j, a[i][j]);
    24. }
    25. }
    26. while (q--)
    27. {
    28. int x1, y1, x2, y2, c;
    29. cin >> x1 >> y1 >> x2 >> y2 >> c;
    30. insert(x1, y1, x2, y2, c);
    31. }
    32. for (int i = 1; i <= n; i++)//求二维前缀和并输出
    33. {
    34. for (int j = 1; j <= m; j++)
    35. {
    36. b[i][j] += b[i][j - 1] + b[i - 1][j] - b[i - 1][j - 1];
    37. cout << b[i][j] << " ";
    38. }
    39. cout << endl;
    40. }
    41. return 0;
    42. }

  • 相关阅读:
    Kali Linux渗透测试技术介绍【文末送书】
    FlinkSQL自定义UDAF使用的三种方式
    加速推进企业信息化建设,SRM采购系统赋能建筑工程产业生态链实现数字化转型
    一文进入Flink CDC 的世界
    【图论】最小生成树
    Android RadioGroup实现多行显示,并保持单选
    Spring Cloud Alibaba 工程搭建
    借我 1 小时,与 1000 人一起参与开源
    【ijkplayer】整体结构总结(一)
    【12. 文件系统管理】
  • 原文地址:https://blog.csdn.net/m0_73612605/article/details/136337404