「一本通 4.1 练习 1」清点人数(loj10116)

题目描述

NK 中学组织同学们去五云山寨参加社会实践活动,按惯例要乘坐火车去。由于 NK 中学的学生很多,在火车开之前必须清点好人数。

初始时,火车上没有学生。当同学们开始上火车时,年级主任从第一节车厢出发走到最后一节车厢,每节车厢随时都有可能有同学上下。年级主任走到第 m 节车厢时,他想知道前 m 节车厢上一共有多少学生,但是他没有调头往回走的习惯。也就是说每次当他提问时,m 总会比前一次大。

输入格式

第一行两个整数 n,k,表示火车共有 n 节车厢以及 k 个事件。

接下来有 k 行,按时间先后给出 k 个事件,每行开头都有一个字母 ABC

  • 如果字母为 A,接下来是一个数 m,表示年级主任现在在第 m节车厢;
  • 如果字母为 B,接下来是两个数 m,p,表示在第 m 节车厢有 p 名学生上车;
  • 如果字母为 C,接下来是两个数 m,p,表示在第 m 节车厢有 p 名学生下车。

学生总人数不会超过 10^55​​。

输出格式

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

样例

样例输入

10 7
A 1
B 1 1
B 3 1
B 4 1
A 2
A 3
A 10

样例输出

0
1
2
3

数据范围与提示

对于 30%的数据,1≤n,k≤10^44​​,至少有 300030003000 个 A

对于 100% 的数据,1≤n≤5×10^5,1≤k≤10^5,,至少有 3×10^4个A

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const long long maxn=500010;
int n, k;
inline void qread(int &x){
    x = 0;
    int ch = getchar();
    while(ch < '0' || ch > '9')        ch =getchar();
    while(ch >='0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
}
struct BItree{
    int data[maxn];
    BItree(){
        memset(data, 0, sizeof(data));
    }
    void add(int x, int v){
        for(; x <= n; x += (x&-x))
            data[x] += v;
    }
    int sum(int x){
        int ans = 0;
        for(; x; x -= (x&-x))
            ans += data[x];
        return ans;    
    }
}bi;
int main(void)
{
    qread(n);
    qread(k);
    while(k--){
        string op;
        cin >> op;
        if(op == "A"){
            int x;
            qread(x);
            printf("%d\n", bi.sum(x));
        }
        else if(op == "B"){
            int x, y;
            qread(x), qread(y);
            bi.add(x, y);
        }
        else{
            int x, y;
            qread(x), qread(y);
            bi.add(x, -y);
        }
    }
}

思路:

  树状数组模板

​​,1k105​​,至少有 3×1043\times 10^43×104​​ 个 A

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9470977.html