首页 > 其他分享 >前缀和与差分

前缀和与差分

时间:2024-08-17 14:26:14浏览次数:15  
标签:x1 前缀 int 差分 x2 num y1 y2

前缀和与差分

前缀和

作用:快速求出数值中某段位置的数值和,降低时间复杂度

一维前缀和

//基本思想
S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]
//实现案例
/*
输入一个长度为n的整数序列。
接下来再输入m个询问,每个询问输入一对l,r。
对于每个询问,输出原序列中从第l个数到第r个数的和。
*/
#include<iostream>
using namespace std;

const int N = 100010;
int n,m;
int q[N],s[N];
int l,r;

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n;i++){
    scanf("%d",&q[i]);
    s[i]=s[i-1]+q[i];
    }
    
    while(m--){
        scanf("%d%d",&l,&r);
        printf("%d\n",s[r]-s[l-1]);
    }
    return 0;
}

二维前缀和

//基本思想,涉及到容斥原理
S[i, j] = 第i行j列格子左上部分所有元素的和
(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
//实例,子矩阵的和
#include<iostream>
using namespace std;

const int N = 1010;
int q[N][N],s[N][N];
int n,m,num;

int main(){
    scanf("%d%d%d",&n,&m,&num);
    for(int i = 1;i<=n;i++)
    for(int j = 1 ;j<=m; j++){
        scanf("%d",&q[i][j]);
        s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+q[i][j];
    }
    
    while(num--){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        printf("%d\n",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
    }
    return 0;
}

差分

可以看成前缀和的逆运算,对原数组某一段区间加上固定数值,降低时间复杂度

一维差分运算

//给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c
//向整数序列变动区间位置频繁进行相加相减操作
#include<iostream>
using namespace std;

const int N =100010; 
int len,num;
int q[N],t[N];

void insert(int l,int r,int num){
    t[l]+=num;
    t[r+1]-=num;
}

int main(){
    scanf("%d%d",&len,&num);
    for(int i = 1;i<=len;i++){
        scanf("%d",&q[i]);
        insert(i,i,q[i]);
    }
    int a,b,c;
    while(num--){
        scanf("%d%d%d",&a,&b,&c);
        insert(a,b,c);
    }
    for(int i = 1;i<=len;i++){
        t[i]+=t[i-1];
        printf("%d ",t[i]);
    }
    return 0;
}

二维差分运算

给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
//差分矩阵
#include <iostream>
using namespace std;

const int N = 1010;
int q[N][N],t[N][N];
int n,m,num;

void insert2d(int x1,int y1,int x2,int y2,int num){
    t[x1][y1]+=num;
    t[x2+1][y1]-=num;
    t[x1][y2+1]-=num;
    t[x2+1][y2+1]+=num;
}

int main(){
    scanf("%d%d%d",&n,&m,&num);
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=m;j++){
            scanf("%d",&q[i][j]);
            insert2d(i,j,i,j,q[i][j]);
        }
        
    while(num--){
        int x1, y1, x2, y2,add;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&add);
        insert2d(x1,y1,x2,y2,add);
    }
    
     for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            t[i][j]+=t[i-1][j]+t[i][j-1]-t[i-1][j-1];
            printf("%d ",t[i][j]);
        }
        printf("\n");
     }
    return 0;
}

标签:x1,前缀,int,差分,x2,num,y1,y2
From: https://blog.csdn.net/DaPeng20020626/article/details/141280170

相关文章

  • leetcode前缀和(2438. 二的幂数组中查询范围内的乘积)
    前言经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。描述给你一个正整数 n ,你需要找到一个下标从 0 开始的数组 powers ,它包含 最少 数目的 2 的幂,且它们的和为 n 。powers 数组是 非递减 顺序的。根据前面描述,构造......
  • “前缀和”专题篇二
    目录和为K的子数组和可被K整除的子数组连续数组矩阵区域和和为K的子数组题目思路我们可能想到的是,从头到尾扫描数组,然后分别计算以该位置为开始,一直到数组末尾,符合和为K的子数组,但是这种方法的时间复杂度是O(N^2),是会超时的,因此需要别的方法来解决。可能又会想到......
  • (路由卷1)-37-前缀列表_K1_IGP分析
    ipprefix前缀列表r2:routerospf1network10.0.0.8area0redistributeriproute-mapintoospfsubnetsrouterripnet10.0.0.0ver2passive-inters3redistributeospf1route-mapintoripmetric5route-mapintoospfpermit10matchipaddressprefix-listpf......
  • 【代码随想录】一、数组:6.前缀和
    二刷的时候发现更新了一些新的题目,尝试写了写后,发现我完全不会ACM输入输出模式。这两天在补前几天没背的八股,写得不够满意(几乎是完全誊代码了),先放着,后面再补充补充吧。1.题目:44.开发商购买土地#include<iostream>#include<vector>#include<climits>usingnamespacestd......
  • D44 2-SAT+前缀优化+二分 CF587D Duff in Mafia
    视频链接: CF587DDuffinMafia-洛谷|计算机科学教育新生态(luogu.com.cn)#include<iostream>#include<cstring>#include<algorithm>#include<vector>usingnamespacestd;constintN=500005;inthead[N],idx,ne[N*6],to[N*6];voidadd(intx,......
  • D43 2-SAT+前缀优化 P6378 [PA2010] Riddle
    视频链接: P6378[PA2010]Riddle-洛谷|计算机科学教育新生态(luogu.com.cn)//2-SAT+前缀优化O(n+m)#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;#definex0(x)x//点#definex1(x)x+n//反点#definep0(x)x+2*n......
  • 前缀和
    1前缀和练习1)跳楼机人数安排题目点击查看代码中文解释#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definedbg(x)cout<<#x<<'='<<x<<endlconstintN=2e5+15;intn,m,q[N],a[N];signedmain(){......
  • 【树上点差分、LCA】Max Flow P
    核心思路[USACO15DEC]MaxFlowP-洛谷sum[u]++,sum[v]++,sum[lca(u,v)]--,sum[fa[lca(u,v)]];本质上就是,对树进行差分自底向上进行统计处理#include<bits/stdc++.h>usingnamespacestd;intn,m;constintN=200000+10;vector<int>G[N];intdep[N],fa[N],hs......
  • 长度最小的子数组 | LeetCode-209 | 双指针+滑动窗口 | 前缀和+二分查找 | Java详细注
    ......
  • 二维差分·学习备忘录
    二维差分为什么我为OI泪目?因为我菜得离谱......引入一维差分用来O(1)修改区间,配合上一维前缀和就是O(N)的查询区间和。差分为前缀和的逆运算。二维差分同理。接下来这道题就用二维差分来解决。\(例题:地毯>>\)地毯题目描述在\(n\timesn\)的格子上有\(m\)个地毯。......