⚡模板,没有多的废话,欢迎点赞收藏~
前缀和模板(对区间求和)
证明:
简单地证明下: 要求num数组【l,r】区间上的和,只需求出前缀数组sum后,sum[r]-sum[l-1]。
① sum[l-1]=num[1]+num[2]+……+num[l-1]
②sum[r] =num[1]+num[2]+……+num[l-1]+num[l]+……num[r-1]+num[r]
②-①可得:sum[r]-sum[l-1]=num[l]+……num[r]
模板:
public class Main {
public static void main(String[] args) {
int n = 10;
int[] arr = new int[n];//下标0开始
long[] sum = new long[n+1];//下标1开始
for(int i=1;i<=n;i++) {
sum[i]=sum[i-1]+arr[i-1];
}
}
}
例题:
问题描述
给定一个长度为 n 的整数数组 a 以及 m 个查询。
每个查询包含三个整数 l,r,k 表示询问 l∼r 之间所有元素的 k 次方和。
请对每个查询输出一个答案,答案对 109+7109+7 取模。
输入格式
第一行输入两个整数 n,m* 其含义如上所述。
第二行输入 n 个整数 a[1],a[2],...,a[n]。
接下来 m 行,每行输入三个整数l,r,k 表示一个查询。
输出格式
输出 m行,每行一个整数,表示查询的答案对 10^9+7 取模的结果。
样例输入
5 3 1 2 3 4 5 1 3 2 2 4 3 3 5 1样例输出
14 99 12评测数据规模:
对于 100100% 的评测数据:1≤≤n,m≤10^5,1≤a[i]≤100,1≤l≤r≤n,1≤k≤5。
AC代码
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] a = new int[100006];
long[][] sum = new long[100007][6];
for(int i=1;i<=n;i++) {
a[i] = sc.nextInt();
for(int j=1;j<=5;j++) {
sum[i][j] = sum[i-1][j]+(long)Math.pow(a[i], j);
}
}
long mod=(long)1e9+7;
for(int i=1;i<=m;i++) {
int l = sc.nextInt();
int r = sc.nextInt();
int k = sc.nextInt();
long re =(sum[r][k]-sum[l-1][k])%mod;
System.out.println(re);
}
}
}
差分模板(对区间进行加减运算)
模板:
public static void chafen1(int[] diff,int l,int r,int d) {
diff[l]+=d;
diff[r+1]-=d;
}
原理:
i位置加value会影响更新数组 i位置以后的位置加value(由于更新数组是差分数组的前缀和),即蓝色和黄色的区域都加value
j+1位置减value会影响更新数组 j+1位置以后的位置减value(由于更新数组是差分数组的前缀和),即黄色区域减value
所以在经过修改差分数组diff[i]+value,diff[j+1]-value后再求差分数组前缀和数组就是更新数组