前缀和、二维前缀和与差分

前缀和

假如给出一串长度为n的数列a1,a2,a3...an,再给出m个询问,每次询问给出L,R两个数,要求给出数列在区间[L,R]的和

普通的方法,时间复杂度为O(n*m)

int a[100005];
for(int i=1;i<=n;i++){
    scanf("%d",&a[i]);
}
int sum=0;
while(m--){
    for(int i=L;i<=R;i++){
        sum+=a[i];
    }
}

前缀和就是前面i个数的总和,对于每个询问,只需要输出a[R]-a[L-1]即可
用前缀和的方法,时间复杂度O(m+n)

for(int i=1;i<=n;i++){
    scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
    a[i]+=a[i-1];
}

差分

假如给出一串长度为n的数列a1,a2,a3...an,再给出m次以及不同的L和R[L,R]操作
操作一:将[L,R]内的元素都加上P
操作二:将[L,R]内的元素都减去P
最后求[L,R]内的元素之和

普通方法时间复杂度为O(m*n)

利用差分

#include <bits/stdc++.h>
using namespace std;
const int manx=1e5+5;
int a[maxn],b[maxn];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=m;i++){
        int l,r,t,p;//t为操作类型,p为加减的大小
        cin>>t>>l>>r>>p;
        if(t==1){//t==1表示加
            b[l]+=p;b[r+1]-=p;//因为操作一我只需对[L,R]区间里的数加p,[R+1,n]这个区间里的数没必要加p,所以需要减掉p。
        }else{//t==0表示减
            b[l]-=p;b[r+1]+=p;
        }
    }
    int add=0;
    for(int i=1;i<=n;i++){
        sum+=b[i];
        a[i]+=a[i-1]+add;
    }
    cin>>l>>r;
    printf("%d\n",a[r]-a[l-1]);
    return 0;
}

原文地址:https://www.cnblogs.com/Emcikem/p/11351353.html

时间: 2024-10-02 07:58:43

前缀和、二维前缀和与差分的相关文章

HDU-6514 Monitor(二维前缀和+差分)

http://acm.hdu.edu.cn/showproblem.php?pid=6514 Problem Description Xiaoteng has a large area of land for growing crops, and the land can be seen as a rectangle of n×m. But recently Xiaoteng found that his crops were often stolen by a group of people,

二维前缀和差分+离散化

/* 二维前缀和求法 a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]; 构建前缀和 int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){//初始化 for(int j=1;j<=m;j++){ int x; scanf("%d",&x); a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+x; } } 输入nm 以

二维前缀和好题hdu6514

#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n,m,a[20000007]; void add(int i,int j,int val){a[(i-1)*m+j]+=val;} int q(int i,int j) { if(i==0||j==0) return 0; return a[(i-1)*m+j]; } int main(){ int p,Q;

openjudge1768 最大子矩阵[二维前缀和or递推|DP]

总时间限制:  1000ms 内存限制:  65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 09 2 -6 2-4 1 -4 1-1 8 0 -2 的最大子矩阵是 9 2-4 1-1 8 这个子矩阵的大小是15. 输入 输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给

Good Bye 2015 C. New Year and Domino 二维前缀

C. New Year and Domino They say "years are like dominoes, tumbling one after the other". But would a year fit into a grid? I don't think so. Limak is a little polar bear who loves to play. He has recently got a rectangular grid with h rows and w

计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和

题目链接:https://nanti.jisuanke.com/t/16445 题意: 给你一个n*n大小的01矩阵,和一个k*k大小的锤子,锤子只能斜着砸,问只砸一次最多能砸到多少个1. 题解: 将原矩阵顺时针旋转45°,二维前缀和预处理,然后枚举每一个可能砸到的正方形之和并取最大. 注:枚举的正方形的四个顶点必须是从原矩阵璇转过来的点,代码中用vis数组判断. #include <iostream> #include <stdio.h> #include <string.

弱校联盟10.7 I. Special Squares(二维前缀和)

题目链接: I. Special Squares There are some points and lines parellel to x-axis or y-axis on the plane. If arbitrary chosen two lines parallel to x-axis and two lines parallel to y-axis, one rectangle, or sometimes a square, will be formed. If a square i

CDOJ 1256 二维前缀和处理

昊昊喜欢运动 他NN 天内会参加MM 种运动(每种运动用一个[1,m][1,m] 的整数表示) 舍友有QQ 个问题 问昊昊第ll 天到第rr 天参加了多少种不同的运动 Input 输入两个数NN , MM (1≤N≤20001≤N≤2000 , 1≤M≤1001≤M≤100 ); 输入NN 个数aiai 表示在第i天昊昊做了第aiai 类型的运动; 输入一个数QQ (1≤Q≤1061≤Q≤106 ); 输入QQ 行 每行两个数 ll , rr (1≤l≤r≤n1≤l≤r≤n ); Output

二维前缀和 - 算法学习 - 输入输出优化

2017-08-27 11:11:38 writer:pprp 二维前缀和主要用到了容斥定理,具体实现还是有点复杂的 详见代码: /* @theme:二维前缀和 @writer:pprp @declare:用到容斥定理 @date:2017/8/27 */ #include <bits/stdc++.h> using namespace std; const int maxn = 1010; int n, m, a[maxn][maxn]; //输入优化 inline int read() {

二维前缀和

一维前缀和 : 这个优化 , 可以在 O (1) 的时间内计算出一个序列的和 , 二维前缀和 : 对于一个矩阵 , 也可以在 O (1) 的时间内计算出矩阵 (x1~x2)( y1 ~ y2 ) 的和 . sum[ i ] [ j ] 表示矩阵 1 ~ i , 1 ~ j 的和 , 那么由容斥原理知 sum[ 0 ] [ j ] 和 sum [ i ] [ 0 ] 均为 0 . 则  s[ x1 ~ x2 ] [ y1 ~ y2 ] = sum[ x2 , y2 ] + sum [ x1 - 1