#P1497. 2023.08.26-MT-第五题-塔子哥的平均数(前缀和)
https://codefun2000.com/p/P1497
题目内容
给定一个正整数数组\(a_1,a_2,...,a_n\),求平均数正好等于k的最长连续子数组的长度
输入描述
第一行输入两个正整数\(n\)和\(k\)
第二行输入n个正整数\(a_i\)
,用来表示数组
\(1 \leq n \leq 1e5\)
\(1≤ k,a_i \leq 1e9\)
输出描述
输出一个整数,表示最长满足题目条件的长度。
样例
输入
5 2
1 3 2 4 1
输出
3
给定一个数组,要求找到一个连续子数组的平均值为kk,并且其长度是符合条件子数组里最长的,求其长度。
可以考虑前缀和的做法来解此题。要求连续子数组平均值为\(k\),让每个数\(a_i^{、}=a_i-k\),那么如果一段连续子数组平均值和为\(k\),则这一段数组的和为\(0\)。\(\sum{a_i^{、}=\sum{a_i}-k*length}=0\).
扩展开来,如果前缀和中出现某两个位置的值相等,那么根据前缀和的定义,他们间的这一段的和为\(0\),那么这一段的长度就是备选答案之一。
所以我们需要使用哈希来存储前缀和中每个数第一次出现的位置,当其又一次出现时,就可以计算长度作为备选答案。
要求平均数为k,预先让每个数减去k,则要求平均数为0,也就是这一段的和为0,可以使用前缀和遍历得到答案
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=1e5+100;
typedef long long ll;
const int mod=1e9+7;
map<ll,int>mp;
int n;
ll a[maxn],sum[maxn],k;
//sum[l,r]=k*len
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]-=k;
sum[i]=(sum[i-1]+a[i]);
}
mp[0]=0;
int ans=0;
for(int i=1;i<=n;i++){
if(mp.count(sum[i])){
ans=max(ans,i-mp[sum[i]]);
}else{
mp[sum[i]]=i;
}
}
cout<<ans<<endl;
return 0;
}