Statistical Sum - Prefix Sum

About the topic:

  Given an integer array of length n and an integer k, you need to find the number of consecutive subarrays in the array that sum to k,

Test sample:

enter:

5 3
1 1 2 1 1

output:

2

  Idea 1:

    Use the for loop to violently enumerate the sub-arrays, and sum + count, the time complexity is O(n^3). (If the data is greater than 100, this idea is definitely Time Limit Exceeded (time overtime), so it needs to be optimized)!

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int a[n],sum=0; //定义数组和计数器 
	for(int i=0;i<n;i++) //for循环输入 
	  scanf("%d",a[i]); //输入下标为i的数 
	for(int i=0;i<n;i++){ //区间i枚举 
		for(int j=0;j<n;j++){ //区间j枚举 
			int ans=0; //区间和计数数组 
			for(int x=i;x<=j;x++) //求出区间[i,j]的和 
			  ans+=a[i]; //计数 
			if(ans==k) //比较 
			  sum++; //计数	  
		}
	}
	cout<<sum<<endl; //输出 
	return 0;
}

Idea 2:

  We can also use the prefix sum to solve this problem. First, preprocess the prefix array sum of a, calculate the sum of the sub-arrays each time, and then perform the double-loop interval enumeration, and then compare it with k. The time complexity is O (n^2). (If the data is not greater than 1500, it can be AC, and there is still room for optimization).

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans 
	sum[0]=0; //将下标为0的地址初始化为0  
	for(int i=1;i<=n;i++){ //进行循环n次读入 
		int a; //定义 
		scanf("%d",&a); //输入 
		sum[i]=sum[i-1]+a; //求前缀和 
	}
	for(int i=1;i<=n;i++) //区间枚举i 
	  for(int j=0;j<n;j++) //区间枚举j 
	    if(sum[i]-sum[j]==k) //求出区间[i,j]的和与k比较 
	      ans++; //计数器加1 
	cout<<ans<<endl; //输出计数器 
	return 0; //结束 
}

Idea 3:

  We can use map (a class defined by the STL library), prefix and optimize. In the idea of ​​using the prefix sum alone, we require whether the sum of a subarray with the subscript i at the end is k, we need to traverse j from 0 to i-1 to find whether there is sum[i]-k= sum[j]. Then we only use map to save the prefix sum of the first i elements, save the value of the prefix sum before the number of occurrences (>i), and finally judge whether the map contains sum[i]-k.

  The time complexity is O(n), which is already very fast, and the data can be AC ​​if it is as large as several million.

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans 
	sum[0]=0; //将下标为0的地址初始化为0  
	map<int,int> p; //定义map 
	for(int i=1;i<=n;i++){ //进行循环n次读入 
		int a; //定义 
		scanf("%d",&a); //输入 
		sum[i]=sum[i-1]+a; //求前缀和 
		p[sum[i]]++; //进行存储 
	}
	for(int i=0;i<n;i++) //进行区间判断 
	  ans+=p[sum[i]+k]; //计数 
	cout<<ans<<endl; //输出 
	return 0; //结束 
}

Summarize:

  This question is a very classic question in prefix sums, which is equivalent to a stepping stone, and there are more difficult differences, two-dimensional prefix sums, etc...

Guess you like

Origin blog.csdn.net/wo_ai_luo_/article/details/129820823