洛谷 U86564 排队形 洛谷 U86564 排队形

题目传送门

题目背景

(JDFZ2019)秋季运动会开始辣!为了使强大的高一 · (6)班有一个更好的精神面貌,班主任(T)老师和体委(LY)(LYB)开始排班级的队形......

题目描述

队形是一个不规则图形(要是规则的话还排什么),分为(N)列,每列有数量不定的同学(排队开始前每列都没有同学)。三个排队形的人有明确的分工:(LY)(代号为(A))负责往队列中加人,(LYB)(代号为(B))负责从队列中减去使队列不协调的人,而(T)老师(代号为(C))只需要检查就可以了。排队开始后,他们会按时间顺序发出不同的指令(为了与其他人区别开,他们每个人发出指令前都会喊出自己的代号):(LY)发出的指令中包括两个数(M_1,K_1),表示第(M_1)列加入(K_1)位同学;(LYB)发出的指令中包括两个数(M_2,K_2),表示第(M_2)列中删除(K_2)位同学;(T)老师发出的指令中也包括两个数(P,Q),表示她现在想知道从第(P)列到第(Q)列的总人数。

输入格式

第一行有两个整数(N,D),表示有(N)列,(D)个指令。

接下来有(D)行,每行开头先包括一个代号((A,B,C)其中的一个),并按题目所述发出他/她的指令。

输出格式

输出行数与(T)老师的提问数相等,每行一个整数,回答(T)老师的问题。

样例输入

10 7
C 1 1
A 1 1
A 3 1
A 4 1
C 1 2
C 1 3
C 1 10

样例输出

0
1
2
3

提示:

数据范围:

对于30%的数据,(1le N,Dle 10^4)(T)老师至少提问(1000)次。

对于全部数据,(1le N,Dle 10^5)(T)老师至少提问(30000)次。

题解:

树状数组的题目。

我觉得应该算是裸题了,最后区间统计利用前缀和的思想就好。

代码:

#include<cstdio>
#include<iostream>
using namespace std;
int n,d;
int tree[500001];
void update(int x,int y)
{
    for(int i=x;i<=n;i+=i&-i)
        tree[i]+=y;
}
int query(int x)
{
    int ret=0;
    for(int i=x;i;i-=i&-i)
        ret+=tree[i];
    return ret;
}
int main()
{
    //freopen("6.in","r",stdin);
    //freopen("6.out","w",stdout);
    scanf("%d%d",&n,&d);
    while(d--)
    {
        char ch;
        cin>>ch;
        if(ch=='A')
        {
            int m,k;
            scanf("%d%d",&m,&k);
            update(m,k);
        }
        else if(ch=='B')
        {
            int m,k;
            scanf("%d%d",&m,&k);
            update(m,-k);
        }
        else if(ch=='C')
        {
            int p,q;
            scanf("%d%d",&p,&q);
            printf("%d
",query(q)-query(p-1));
        }
    }
    return 0;
}