参考链接:https://blog.csdn.net/hzk_cpp/article/details/80407014
题目链接:https://www.acwing.com/problem/content/102/
前缀和:
就是一个数组,要快速静态查询区间和,我们只要处理一个数组时A[i]=a[1]+a[2]+...+a[i].
A[1]=a[1]
A[2]=a[1]+a[2]
A[3]=a[1]+a[2]+a[3]
A[4]=a[1]+a[2]+a[3]+a[4]
......
例如:求[2,4]的区间和,A[4]-A[1]=a[2]+a[3]+a[4]=a[1]+a[2]+a[3]+a[4]-(a[1])
那么查询区间[l,r]的时候只要输出A[r]-A[l-1].
那么这是时候预处理是O(n)的,查询一次是O(1).
在很多情况下这种算法都是可行的,但是必须满足区间减法的性质.
代码预处理如下:
for (int i=1;i<=n;i++)
A[i]=A[i-1]+a[i];
差分:
只不过它可以配套前缀和使用.
差分是一种很巧妙的思想,它的主要用途是维护一个区间的快速修改(加减),但查询是单次的时候.O(n+m)
这种思想的主体就是维护一个数组A,其中A[i]=原数组a[i]-a[i-1].
那么就是刚好与前缀和有点像.
也是互逆的运算.
那么这怎么快速维护呢?
也就是说给区间[l,r]+num.
那么就是给开头A[l]+num,再给结尾A[r+1]-num.
很好理解啊.
那么实现如下:
void add(int l,int r,int num){
A[l]+=num;A[r+1]-=num;
}
那么最后需要查询了,就这样处理一下:
for (int i=1;i<=n;i++)
a[i]=a[i-1]+A[i];
那么就是原来的数组了.
时间复杂度O(1)修改,O(n)查询.
public class Main { //前缀和 public static void fun(int arr[],int A[]){ /* A[1]=a[1] A[2]=a[1]+a[2] A[3]=a[1]+a[2]+a[3] A[4]=a[1]+a[2]+a[3]+a[4] */ for (int i=1;i<arr.length;i++) A[i]=A[i-1]+arr[i]; } public static int query(int l,int r,int A[]){ //查询区间[l,r]的时候只要输出A[r]-A[l-1] return A[r]-A[l-1]; } //差分 public static void fun2(int arr[],int A[]){ for (int i=1;i<arr.length;i++) A[i]=arr[i]-arr[i-1]; } public static void add(int l,int r,int num,int A[],int arr[]){ A[l]+=num;A[r+1]-=num; for (int i=1;i<A.length;i++) arr[i]=arr[i-1]+A[i]; } public static void main(String[] args) { int arr[]={0,1,2,3,4}; int A[]=new int[5]; // fun(arr, A); // System.out.println(query(1, 3, A)); // System.out.println(query(2, 4, A)); fun2(arr, A); add(1, 3, 9, A, arr); for (int i = 1; i < arr.length; i++) { System.out.println(arr[i]); } } }
IncDec sequence 题解