【ACWing】1267. 清点人数

题目地址:

https://www.acwing.com/problem/content/1269/

NK中学组织同学们去五云山寨参加社会实践活动,按惯例要乘坐火车去。由于NK中学的学生很多,在火车开之前必须清点好人数。初始时,火车上没有学生,当同学们开始上火车时,年级主任从第一节车厢出发走到最后一节车厢,每节车厢随时都有可能有同学上下。年级主任走到第 m m m节车厢时,他想知道前 m m m节车厢上一共有多少学生。他没有调头往回走的习惯,也就是说每次当他提问时, m m m总会比前一次大。

输入格式:
第一行两个整数 n , k n,k n,k,表示火车共有 n n n节车厢以及 k k k个事件。接下来有 k k k行,按时间先后给出 k k k个事件,每行开头都有一个字母 A A A B B B C C C
如果字母为 A A A,接下来是一个数 m m m,表示年级主任现在在第 m m m节车厢;
如果字母为 B B B,接下来是两个数 m , p m,p m,p,表示在第 m m m节车厢有 p p p名学生上车;
如果字母为 C C C,接下来是两个数 m , p m,p m,p,表示在第 m m m节车厢有 p p p名学生下车。
学生总人数不会超过 1 0 5 10^5 105

输出格式:
对于每个事件 A A A,输出一行,一个整数,表示年级主任的问题的答案。

数据范围:
1 ≤ n ≤ 5 × 1 0 5 1≤n≤5×10^5 1n5×105
1 ≤ k ≤ 1 0 5 1≤k≤10^5 1k105

即要求实现单点修改与查询前缀和,可以用树状数组来做。代码如下:

#include <iostream>
using namespace std;

const int N = 5e5 + 10;
int n, k;
int tr[N];

int lowbit(int x) {
    
    
    return x & -x;
}

int sum(int x) {
    
    
    int res = 0;
    for (int i = x; i; i-= lowbit(i)) res += tr[i];
    return res;
}

void add(int s, int x) {
    
    
    for (int i = s; i <= n; i += lowbit(i)) tr[i] += x;
}

int main() {
    
    
    scanf("%d%d", &n, &k);
    while (k--) {
    
    
        char op[2];
        scanf("%s", op);
        if (*op == 'A') {
    
    
            int x;
            scanf("%d", &x);
            printf("%d\n", sum(x));
        } else {
    
    
            int s, x;
            scanf("%d%d", &s, &x);
            if (*op == 'B') add(s, x);
            else add(s, -x);
        }
    }

    return 0;
}

每次询问时间复杂度 O ( log ⁡ n ) O(\log n) O(logn),空间 O ( n ) O(n) O(n)

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/121745885