求和求差2---一维差分

目录

基础:

区间修改问题

一维差分实现原理

例题:一维差分

for(int i=l;i<=n;i++) b[i]-a[i]-a[i-1];for(int i=1;i<=m;i++){int l=in.nextInt(),r=in.nextInt(),d=in.nextInt();b[l]=b[l]+d;b[r+1]=b[r+1]-d;

}for(int i=1;i<=n;i++) c[i]=c[i-1]+b[i];

例题:小蓝的操作


基础:

字符串输入:

sc.nextLine();//扫描空行

String s=sc.nextLine();

区间修改问题


给定一个长度为 n 的序列 a.
再给定 m 组操作,每次操作给定 3 个正整数l,r,d,表示对 al~r中的所有数增加d。
最终输出操作结束后的序列 a。
暴力做法为写一个循环,每次修改l~r之间的所有数字。
时间复杂度最坏为O(nm)。

一维差分实现原理

定义差分数组 b, bi= ai — ai-1。
b1= a1
b2 = a2 — a1
b3 = a3 - a2
b4= a4 -a3。
我们对数组 b求前缀和得到新数组 c。
c1 = b1 = a1 = a1
c2 = b1 + b2 = a1 + a2 - a1= a2
c3 = b1 + b2 + b3 = a1 + a2 - a1+ α3 - a2 = a3
c4 = b1 + b2 + b3 + b4 =a1 + a2 -a1 + a3 - a2 + a4 - a3 = a4
我们能得到一个结论,差分数组求前缀和得出的就是原数组

我们现在将b1 +1。再去求一个前缀和数组。
c1 = b1 + 1 = a1 + 1 = a1+1
c2 = b1 + 1 + b2 = a1 + a2 -a1 + 1 = a2+ 1
c3 = b1 + 1 + b2 + b3 = a1 + a2 - a1 + a3 - a2 + 1 = a3 + 1
c4= b1+1+b2 +b3+b4 = a1+a2-a1+a3-a2+a4-a3 +1 = α4+1
我们再将b4-1。再去求一个前缀和数组。
c1= b1+1 =a1 +1 = a1+1
c2 = b1 + 1 + b2 = a2 + 1 + a2 - a1= a2+ 1
c3 = b1+ 1 + b2 + b3 =ar+1 + a2 -a1 + a3 - a2 = a3 + 1
c4 = b1+ 1 + b2 + b3 + b4- 1 = a1 + 1 + a2 -a1 + a3 - a2 + a4-a3 -1 = a4
因此,对差分数组 b。将bl+ d, b(r+1)-d,求解前缀和后,即可得到修改后的数组 c.
这种做法的复杂度为 O(n+m)。


差分数组常见性质:
如果差分数组除了b1 以外所有值均为0,则说明数组a的值全部一样。

例题:一维差分

static int N=(100010);
static int a[]=new int[N],b[]=new int[N],c[]=new int[N];
static void solve(){
int n=in.nextInt(),m=in.nextInt();
for(int i=1;i<=n;i++) a[i]=in.nextInt();


for(int i=l;i<=n;i++) b[i]-a[i]-a[i-1];
for(int i=1;i<=m;i++){
int l=in.nextInt(),r=in.nextInt(),d=in.nextInt();
b[l]=b[l]+d;
b[r+1]=b[r+1]-d;

}
for(int i=1;i<=n;i++) c[i]=c[i-1]+b[i];


for(int i=l;i<=n;i++) out.print(c[i]+"");

}


例题:小蓝的操作

代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class Main{
    static int N=100010;
    static int a[]=new int[N], b[]=new int[N];
    public static void main(String[] args) {
      Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        long res=0;
        for(int i=1;i<=n;i++) {
            a[i] = in.nextInt();
            b[i]=a[i]-a[i-1];
            if(b[i]>0){
                res=res+b[i];
            }
        }
        System.out.println(res-1);
       
    }}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值