ACM训练赛第19场补题
问题 A: At Least Average
时间限制: 1 Sec 内存限制: 128 MB
题目描述
Blake plays a video game that has n levels. On each level, she can earn in between 0 and 10 points, inclusive. The number of points she gets on a level must be an integer. She has set up a goal for herself to equal or beat a particular average. In order to make her performance seem impressive, she’s decided that she wants to count the number of intervals (sets of consecutive levels) where she’s equaled or beaten her target average.
We define an interval [i, j], with 1 ≤ i ≤ j ≤ n, to be each level starting at level i and ending at level j, including level j. For example, if Blake played 5 levels with her scores being 5, 1, 2, 4 and 6, and Blake’s target average was 3, then here are the following intervals where she equaled or beat her target average:
[1, 1] with average 5
[1, 2] with average 3
[1, 4] with average 3
[1, 5] with average 3.6
[2, 5] with average 3.25
[3, 4] with average 3
[3, 5] with average 4
[4, 4] with average 4
[4, 5] with average 5
[5, 5] with average 6
Blake can make the impressive statement that on 10 intervals her average score was 3 or more.
The Problem
Given the number of levels Blake has played in her video game, her scores on each level, and the average value she’d like to equal or beat, determine the number of intervals that she equaled or beat the given average.
输入
The first line of input will consist of a single positive integer, v (v ≤ 10), representing the number of input cases to process. Input for each case follows, one case taking two lines. The first line of input for each case contains two positive integers, n (n ≤ 100000), and a (a ≤ 10), separated by spaces, representing the number of levels of the video game and the average Blake wants to obtain, respectively. The following line contains n space separated integers, each in between 0 and 10 inclusive, representing Blake’s score on each of the n levels, in order.
输出
For each input case, output a single integer on a line by itself representing the number of intervals where Blake obtained her desired average or higher.
样例输入 Copy
2
5 3
5 1 2 4 6
9 6
10 1 10 1 10 1 10 1 10
样例输出 Copy
10
15
思路
求某个数组里有多少个区间的区间平均值大于等于某个固定的数。
权值树状数组。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 2000000 + 10;
const int base = 1000000;
int n;
int a[MAXN];
long long sum[MAXN];
int c[MAXN];
int lowbit(int x) {
return x & (-x);
}
int query(int x) {
int ret = 0;
while (x > 0) {
ret += c[x];
x -= lowbit(x);
}
return ret;
}
void update(int i, int k) {
while (i <= 2000008) {
c[i] += k;
i += lowbit(i);
}
}
int main() {
int T;
scanf("%d", &T);
while (T --) {
memset(c,0,sizeof(c));
memset(sum,0,sizeof(sum));
scanf("%d", &n);
int avg;
scanf("%d", &avg);
for (int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
a[i] = a[i] - avg ; // 将所有数减去平均值,看有多少数大于等于零
}
for (int i = 1; i <= n; i ++) {
sum[i] = sum[i - 1] + a[i]; // 求前缀和
}
for(int i = 1; i <= n; i ++) {
sum[i] += base; // 防止负数,加上某个数变成正数
}
update(base, 1);
long long cnt = 0;
for (int i = 1; i <= n; i ++) {
cnt += query(sum[i]); // 小于等于当前数的数量个数
// cout << sum[i] << " " << query(sum[i]) << endl;
update(sum[i] , 1); // 使树状数组sum[i]下标位置加1
}
cout << cnt << endl;
}
return 0;
}
/**************************************************************
Problem: 19121
User: 2021Team066
Language: C++
Result: 正确
Time:276 ms
Memory:64524 kb
****************************************************************/