- 欧浩 的博客
统计区间
- @ 2025-7-17 17:33:04
统计区间 题解
题意
做法
1.暴力
简单粗暴,直接上代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int TOP=2e5+5;
int n,m;
int a[TOP];
int sum[TOP];
int ans;
signed main()
{
// freopen("tjqj.in","r",stdin);
// freopen("tjqj.out","w",stdout);
int f,k;
cin>>n>>m;
for(f=1;f<=n;f++)
{
cin>>a[f];
sum[f]=sum[f-1]+a[f];
}
for(f=1;f<=n;f++)
for(k=1;k<=f;k++)
if(sum[f]-sum[k-1]==m)
ans++;
cout<<ans;
return 0;
}
结果很明显

2.优化
开始优化,来分析一下: 通过之前暴力代码的经验可知,所选区间的前后指针都去枚举的话肯定要超时,所以开始思考枚举一个指针。我们的目标永远是和为K,另一个指针的加入也就是把多余的部分去掉,使原区间(之前确定了一条边,另一条边暂定数组边界)在删改后满足和为K的条件。我们将指针历来能削去的数值记录一下,到需要用的时候调用就行了。由于能削去同一数值的指针不只有一个(数组中包含负数),所以用"map<int,int>"来存储。键值表示能削掉多少值,而整个"map"存储的是有多少选择(即有多少指针满足削掉这一数值)
接下来是AC代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int TOP=2e5+5;
int n,m;
int sum[TOP];
map<int,int> t;
int ans;
signed main()
{
// freopen("tjqj.in","r",stdin);
// freopen("tjqj.out","w",stdout);
int f,k;
cin>>n>>m;
t[0]++;
for(f=1;f<=n;f++)
{
int num;
cin>>num;
sum[f]=sum[f-1]+num;
if(t[sum[f]-m]>0)
ans+=t[sum[f]-m];
t[sum[f]]++;
}
cout<<ans;
return 0;
}

诚信做人,请勿抄袭