前缀和(一维和二维)

  • 1.前缀和

前缀和也就是将【l,r】区间内的数据进行累加在这里插入图片描述
注意事项:
模板
S[i] = a[1] + a[2] + … a[i]
a[l] + … + a[r] = S[r] - S[l - 1]

1.数组从1开始可以保证公式的适用性。
则,
【1,10】=S10-S0(如果S0有数据就不对应了)
【l r】=Sr - Sl-1;

题目:
输入一个长度为 n 的整数序列。
接下来再输入 m 个询问,每个询问输入一对 l,r。
对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数数列。

c++:
在这里插入图片描述

java、


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

/*
* 输入一个长度为 n 的整数序列。
接下来再输入 m 个询问,每个询问输入一对 l,r。
对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。
*
5 3
2 1 3 6 4
1 2
1 3
2 4*/
public class Main {
    //1,注意计数从1开始计数,方便使用公式
    //2,开辟新数组放置新的数据
    static int Number = 100010;
    public static int frontadd(int[] S,int l,int r){
        //利用公式
        int add = S[r] - S[l-1];
        return add;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc =new Scanner(System.in);
        //先输入
        int N = sc.nextInt();
        int q = sc.nextInt();
        int[] A = new int[N+1];
        int[] S = new int[N+1];
        S[0] =0;
        //数组
        for(int i =1;i<=N;i++){
            A[i] = sc.nextInt();
        }
        //计算出数组的和Sn
        for(int k=1;k<=N;k++){
            S[k] = S[k-1]+A[k];
        }
        for(int j=0;j<q;j++){
            //每次接收两个数据
            int qus1 = sc.nextInt();
            int qus2 = sc.nextInt();
            int add = frontadd(S,qus1,qus2);
            System.out.println(add);
        }

    }
}

  • 二维前缀和
    二维数组,容斥原理
    在这里插入图片描述

模板
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]

单个的怎么进行计算:
Sij = Si-1,j +Si,j-1-Si-1j-1+aij
减去重复的数据

题目:

输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。

对于每个询问输出子矩阵中所有数的和。

import java.util.Scanner;

/*第一行包含三个整数 n,m,q。接下来 n 行,每行包含 m 个整数,表示整数矩阵。接下来 q 行,每行包含四个整数 x1,y1,x2,y2,表示一组询问。
输出格式共 q 行,每行输出一个询问的结果。
数据范围
1≤n,m≤1000,
1≤q≤200000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤矩阵内元素的值≤1000*/
public class Main {
    static int M=1000;
    static int Q = 200000;
    //main
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int q = sc.nextInt();//几组查询
        //定义二维数组
        int[][] A = new int[n+1][m+1];
        //定义S和的数组
        int[][] S = new int[n+1][m+1];
        //输入数组
        A[0][0]=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                A[i][j] = sc.nextInt();
            }
        }
        //计算和
        S[0][0] =0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                S[i][j] = S[i][j-1]+S[i-1][j]-S[i-1][j-1]+A[i][j];//所有的和的放在数组里面
            }
        }

        //输入两个坐标()()左上角和右上角
        for(int i=0;i<q;i++){
            //i
            int Xi = sc.nextInt();
            int Yi = sc.nextInt();
            int Xj = sc.nextInt();
            int Yj = sc.nextInt();
            //求之间的围城的面积
            int s = mianji(S,Xi,Yi,Xj,Yj);
            System.out.println(s);
        }

    }
    public static int mianji(int[][] S,int Xi,int Yi,int Xj,int Yj){
        int s = S[Xj][Yj] - S[Xi-1][Yj]-S[Xj][Yi-1]+S[Xi-1][Yi-1];
        return s;
    }
}

注意面积公式!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值