蓝桥杯java(前缀和和差分)

795. 前缀和

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

接下来再输入 m 个询问,每个询问输入一对 l,r

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式

第一行包含两个整数 n  m

第二行包含 n 个整数,表示整数数列。

接下来 m行,每行包含两个整数 l  r,表示一个询问的区间范围。

输出格式

 m 行,每行输出一个询问的结果。

数据范围

1≤lrn,
1≤n,m≤100000,
−1000≤数列中元素的值≤1000

输入样例:

5 3

2 1 3 6 4

1 2

1 3

2 4

输出样例:

3

6

10

程序:

import java.util.*;
import java.io.*;
public class Main {
    public static final int M = 100010;
    public static void main(String args[])
    {
        Scanner N = new Scanner(System.in);
        int n = N.nextInt();
        int m = N.nextInt();
        int [] a = new int [M];
        int l,r,i;
        for(i = 1;i <= n; i++)
        {
            a[i]= N.nextInt();
        }
        int [] S = new int [M];
        for(i = 1; i <=n;i++)
        {
            S[i] = S[i-1] + a[i];
        }
        for(i = 1;i<=m;i++)
        {
            l = N.nextInt();
            r = N.nextInt();
            System.out.println(S[r]-S[l-1]);
        }
    }
}

总结:

一维前缀和算法

1.记住公式s[i] = s[i-1] + a[i];

2.求区间和 System.out.println(“s[r]-s[l-1]”);

3.注意数组从i=1开始取,可以避免很多麻烦。在定义数组规模的时候可以先定义一个常量,方便填写和后期修改。

796. 子矩阵的和

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

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

输入格式

第一行包含三个整数 nmq

接下来 n 行,每行包含 m个整数,表示整数矩阵。

接下来 q 行,每行包含四个整数 x1,y1,x2,y2,表示一组询问。

输出格式

 q 行,每行输出一个询问的结果。

数据范围

1n,m1000,
1q200000,
1x1x2n,
1y1y2m,
1000矩阵内元素的值1000

输入样例:
3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4
输出样例:
17
27
21

程序:

import java.io.*;
import java.util.*;
public class Main{
    public static final int M = 1010;
    public static void main(String args[])
    {
        Scanner N = new Scanner(System.in);
        int n = N.nextInt();
        int m = N.nextInt();
        int q = N.nextInt();
        int i,j;
        int [][] a =new int[M][M];
        int [][] s =new int[M][M];
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                a[i][j]=N.nextInt();
            }
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                s[i][j]= s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
            }
        }
        int p;
        for(p=1;p<=q;p++)
        {
        int x1 = N.nextInt();
        int y1 = N.nextInt();
        int x2 = N.nextInt();
        int y2 = N.nextInt();
        System.out.println(s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
        }
    }
}

总结:

二维数组前缀和:

把它当作矩阵来看待

1.公式:s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i-1][j-1]

2.求子矩阵和:System.out.println(s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);

797. 差分

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

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

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

输入格式

第一行包含两个整数 n  m

第二行包含 n 个整数,表示整数序列。

接下来 m 行,每行包含三个整数 lrc,表示一个操作。

输出格式

共一行,包含 n 个整数,表示最终序列。

数据范围

1n,m100000,
1lrn,
1000c1000,
1000整数序列中元素的值1000

输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2

程序:

import java.util.*;

public class Main{

    public static final int M = 100010;
    public static int []b = new int[M];
    public static void main(String args[])
    {


        Scanner N = new Scanner(System.in);
        int n = N.nextInt();
        int m = N.nextInt();
        int i;
        int []a = new int[M];
        for(i=1;i<=n;i++)            a[i]= N.nextInt();
        for(i=1;i<=n;i++)           cf(i,i,a[i]);
        for(i=1;i<=m;i++)
        {
            int l = N.nextInt();
            int r = N.nextInt();
            int c = N.nextInt();
            cf(l,r,c);
        }
        for(i=1;i<=n;i++) b[i]+=b[i-1];
        for(i=1;i<=n;i++)
            System.out.print(b[i]+" ");
    }

    public static void cf(int l, int r, int c) {
            b[l]+= c;
            b[r+1]-= c;
        }

    }


总结:

1.自己定义一个差分的方法:

这个方法cf(I,I,a[i])经过循环可以得到数组a得差分数组b

即b[1]=a[1],b[2]=a[2]-a[1]~~~

public static void cf(int l, int r, int c) {
           
b[l]+= c;
           
b[r+1]-= c;
       
}
2.如果求给一个区间[l,r]都加c的操作,则只需要在所需的差分数组的区间左端加上c,在差分数组右端减去c,在求前缀和的时候l到r区间都会加c。

798. 差分矩阵

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

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

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

输入格式

第一行包含整数 n,m,q

接下来 n 行,每行包含 m 个整数,表示整数矩阵。

接下来 q 行,每行包含 5个整数 x1,y1,x2,y2,c表示一个操作。

输出格式

 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

数据范围

1n,m1000,
1q100000,
1x1x2n,
1y1y2m,
1000c1000,
1000矩阵内元素的值1000

输入样例:
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
输出样例:
2 3 4 1
4 3 4 1
2 2 2 2

程序:

import java.util.*;
public class Main{
    public static final int M = 1010;
    public static int [][]b = new int[M][M];
    public static void main(String args[])
    {
        Scanner N = new Scanner(System.in);
        int n = N.nextInt();
        int m = N.nextInt();
        int q = N.nextInt();
        int [][]a = new int[M][M];
        int i,j,p;
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                a[i][j] = N.nextInt();
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                cf(i,j,i,j,a[i][j]);
        for(p=1;p<=q;p++)
        {
            int x1 = N.nextInt();
            int y1 = N.nextInt();
            int x2 = N.nextInt();
            int y2 = N.nextInt();
            int c = N.nextInt();
            cf(x1,y1,x2,y2,c);
        }
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++) {
                b[i][j] += b[i-1][j]+b[i][j-1]-b[i-1][j-1];
            }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++) {
                System.out.print(b[i][j]+" ");
            }
            System.out.println("");
        }

    }
    public static void cf(int x1,int y1,int x2,int y2,int c)
    {
        b[x1][y1] +=c;
        b[x1][y2+1] -=c;
        b[x2+1][y1] -=c;
        b[x2+1][y2+1] +=c;
    }
}

总结:

差分矩阵

1.定义差分矩阵方法

cf(I,j,I,j,a[i][j]),更新b矩阵(a矩阵是b矩阵的前缀和)

public static void cf(int x1,int y1,int x2,int y2,int c)
    {
       
b[x1][y1] +=c;
       
b[x1][y2+1] -=c;
       
b[x2+1][y1] -=c;
       
b[x2+1][y2+1] +=c;
   
}

2.注意最后求b[i][j]的时候:b[i][j] += b[i-1][j]+b[i][j-1]-b[i-1][j-1];

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值