平均数

题目大意

平均数

给定长度为 \(n\) 的非负整数序列 \(a_1,a_2,\cdots,a_n\),问有多少个区间 \([l,r](1\le l\le r\le n)\) 满足 \(a_l,a_{l+1},\cdots,a_{r}\) 的平均数为给定非负整数 \(k\)

思路

发现直接维护平均值很难维护,于是就有了一个平均数非常经典小trick,不是直接维护一个区间的平均值,而是现将每一个数都减去 \(k\),如果有一个区间和加起来为零,就说明这个区间的平均值为 \(k\)

举个栗子:

$\{1\ 3\ 5\} $,假设 \(k = 3\),则将每个元素减 \(k\),得到 \(-2\ 0\ 2\),发现 \([1, 3]\) 这段区间的和为 \(0\),所以 \([1, 3]\) 这段区间的平均值就为 \(3\)

有了这个技巧,就可以做这题了。首先先将所有元素减去 \(k\),由于要求有多少个区间的平均值为 \(k\),所以需要用到前缀和,问题就转化成了有多少个区间 \(s[r] - s[l-1] = 0\)

枚举右端点,要求有多少个左端点 \(l\) 满足 \(s[r] - s[l-1] = 0\),移项一下就是求有多少个左端点满足 \(s[l] = s[r]\),用 \(map\) 维护再 \(r\) 之前有多少 \(s\)\(s[r]\) 即可。

代码

#include <bits/stdc++.h>
using namespace std;

const long long N = 100010;
long long n, k;
map<long long, long long> box;
map<long long, bool> ;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin >> n >> k;
    long long s = 0, ans = 0; box[0]++;
    for (long long i = 1; i <= n; i++) {
        long long a; cin >> a;
        s += a - k;
        ans += box[s];
        box[s]++;
    }
    cout << ans << endl;
    return 0;
}
posted @ 2025-10-03 12:26  wuzihenb  阅读(17)  评论(0)    收藏  举报