前缀和差分(java版)

一维前缀和

简单来说:我们有一个数组x和它的前缀和数组y,他们满足以下公式。 y 0 = x 0 y 1 = x 0 + x 1 y 2 = x 0 +
x 1 + x 2 … 即 y[n]=x[1]+x[2]+…+x[n]。

Acwing前缀和题目链接

import java.util.Scanner;

public class 一维前缀和 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        int[] arr=new int[n+1];
        //为了方便,数组下标从1开始
        for (int i = 1; i <=n ; i++) {
            arr[i]=sc.nextInt();
        }
        //下标从1开始,就可以避免l=1的特判
        int[] sum=new int[n+1];
        for (int i = 1; i <=n ; i++) { 
            sum[i]=sum[i-1]+arr[i];//前缀和的初始化
        }
        while (m-->0){  //m次询问(询问数组的区间和)
            int l=sc.nextInt();   
            int r=sc.nextInt();
            System.out.println(sum[r]-sum[l-1]);
        }

    }
}

二维前缀和

应用:快速求子矩阵的和

原题链接

import java.util.Scanner;

public class 二维前缀和 {
    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[][] map=new int[n+1][m+1];
        for (int i = 1; i <=n ; i++) {
            for (int j = 1; j <=m ; j++) {
                map[i][j]=sc.nextInt();
            }
        }
        int[][] sum=new int[n+1][m+1];
        //初始化二维数组,防止下标越界
        sum[0][0]=0;
        sum[0][1]=0;
        sum[1][0]=0;
        //求二维前缀和
        for (int i = 1; i <=n ; i++) {
            for (int j = 1; j <=m ; j++) {
                sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+map[i][j];
            }
        }
        while (q-->0){
            int x1=sc.nextInt();
            int y1=sc.nextInt();
            int x2=sc.nextInt();
            int y2=sc.nextInt();
            //求子矩阵的面积
            System.out.println(sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]);

        }
    }
}

3.一维差分

原题链接

import java.util.Scanner;

public class 一维差分 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        int[] arr=new int[n+2];
        int[] cha=new int[n+2];
        for (int i = 1; i <=n ; i++) {
            arr[i]=sc.nextInt();
        }
        for (int i = 1; i <=n ; i++) {
            cha[i]=arr[i]-arr[i-1];
        }
        while (m-->0){
            int l=sc.nextInt();
            int r=sc.nextInt();
            int c=sc.nextInt();
            cha[l]+=c;
            cha[r+1]-=c;
        }
        for (int i = 1; i <=n ; i++) {
           arr[i]=arr[i-1]+cha[i];
        }
        for (int i = 1; i <=n ; i++) {
            System.out.print(arr[i]+" ");
        }

    }
}

4.二维差分

数据大时要用BuffereRead输入

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

public class 二维差分 {

    static int N=1005;

    static int[][] a=new int[N][N];
    static int[][] b=new int[N][N];

    public static void main(String[] args) throws IOException {

        int n=Reader.nextInt();
        int m=Reader.nextInt();
        int q=Reader.nextInt();
        for (int i = 1; i <=n ; i++) {
            for (int j = 1; j <=m ; j++) {
                a[i][j]=Reader.nextInt();
            }
        }

        //进行差分操作
        for (int i = 1; i <=n ; i++) {
            for (int j = 1; j <=m ; j++) {
                insert(i,j,i,j,a[i][j]);
            }
        }

        while (q-->0){
            int x1=Reader.nextInt();
            int y1=Reader.nextInt();
            int x2=Reader.nextInt();
            int y2=Reader.nextInt();
            int c=Reader.nextInt();
            insert(x1,y1,x2,y2,c);
        }
        //还原原数组
        for (int i = 1; i <=n ; i++) {
            for (int j = 1; j <=m ; j++) {
                b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
            }
        }
        for (int i = 1; i <=n ; i++) {
            for (int j = 1; j <=m ; j++) {
                System.out.print(b[i][j]+" ");
            }
            System.out.println();
        }

    }

    //差分操作
    static void insert(int x1,int y1,int x2,int y2,int c){
        b[x1][y1]+=c;
        b[x2+1][y1]-=c;
        b[x1][y2+1]-=c;
        b[x2+1][y2+1]+=c;
    }
}
class Reader{
    static BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer tokenizer=new StringTokenizer("");

    static String next() throws IOException {
        while (!tokenizer.hasMoreTokens()){
            tokenizer=new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值