ACM训练赛第19场补题

这篇博客介绍了如何解决ACM训练赛中的一个问题——计算Blake在每个连续级别区间中达到或超过目标平均分的次数。通过使用树状数组(权值树状数组)的数据结构,博主提供了算法实现来高效地找出所有符合条件的区间,并给出了样例输入和输出。算法主要涉及数组处理、前缀和计算和区间平均值的计算,对于理解和应用动态数据结构有一定的参考价值。
摘要由CSDN通过智能技术生成

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
****************************************************************/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值