【题解】[ IOI 2001] Mobile Phones(二维树状数组)

题面

【题目描述】
假设 T a m p e r e Tampere Tampere区域的第四代手机基地站运行如下。该区域被划分为一些正方形(方阵)。这些正方形构成一个 S S S S S S的矩阵,矩阵行和列的编号从 0 0 0 S − 1 S-1 S1。每个正方形包含一个基地站。由于一个手机可能从一个正方形移动到另一个正方形,或者手机可能开机或关机,所以,在一个正方形内正在使用的手机数目是随时变化的。有时,每个基地站需要将正在使用的手机数的变化用矩阵的行和列报告给主基地站。
请你写一个程序,接收这些报告并回答有关任一个长方形区域内当前正在使用的手机总数的查询。
【输入】
输入是从标准输入读入整数,对查询的回答是把一个整数写到标准输出。输入格式如下。每个输入占用一行,每行由一个标志数和一些参数构成,标志数和这些参数的格式见下表。

标志数参 数意 义
0S用全零来初始化矩阵,大小为 S´S. 该标志数仅仅给出一次,并将是第一个标志数。
1X Y A将A的值加到矩阵表方阵(X,Y)当前正在使用的手机数目中。A 可正可负。
2L B R T在方阵(X,Y)中查询当前正在使用的手机数的总和,其中 L ≤ X ≤ R , B ≤ Y ≤ T L \leq X \leq R,B \leq Y \leq T LXRBYT
3结束程序该标志数仅仅给出一次并将是最后一个标志数。

所有数值将始终在范围内,因而不需要检查。特别是,当 A A A为负时,可以假定它不会把正方形内的数目减到 0 0 0以下。范围的序号从 0 0 0开始。例如,对于一个 4 4 4* 4 4 4的表, X X X Y Y Y的变化范围为 0 ≤ X ≤ 3 , 0 ≤ Y ≤ 3 0\leq X\leq 3, 0\leq Y\leq 3 0X3,0Y3
对于一个标志数非(不是) 2 2 2的行,你的程序不应回答任何内容。如果标志数是 2 2 2,你的程序应当将答案以一个整数的形式写到标准输出来回答查询。
【输出】
对于每一个标志数为 2 2 2的,输出结果。
【样例输入】

0 4 
1 1 2 3  
2 0 0 2 2
3

【样例输出】

3

【数据范围】

矩阵表大小 S S S S S S 1 ✖ 1 ≤ S ✖ S ≤ 1024 ✖ 1024 1✖1 \leq S✖S \leq 1024✖1024 11SS10241024
任意时间的单元值 V V V 0 ≤ V ≤ 2 15 – 1 0 \leq V \leq 2^{15} –1 0V2151 ( = 32767 =32767 =32767)
更新量 A A A − 2 15 ≤ A ≤ 2 15 – 1 -2^{15} \leq A \leq 2^{15}–1 215A2151 ( = 32767 = 32767 =32767)
输入中标志数的数目 U U U 3 ≤ U ≤ 60002 3 \leq U \leq 60002 3U60002
整个矩阵表中手机数的最大值 M M M M = 2 30 M= 2^{30 } M=230

20 20 20个输入中, 16 16 16个输入(矩阵表)的大小最多是 512 ✖ 512 512✖512 512512

算法分析

二维树状数组模板题目
本题对矩阵进行操作,对矩阵进行询问,方法与一维树状数组类似,才有二维树状数组。

参考程序

#include<bits/stdc++.h>
using namespace std;
int n;
long long c[N][N];
long long ans;
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y,long long k)	//区间更新
{
    int i=x;
    while(i<=N)
    {
        int j=y;
        while(j<=N)
        {
            c[i][j]+=k;
            j+=lowbit(j);
        }
        i+=lowbit(i);
         
    }
}
long long sum(int x,int y)		//区间求和,矩阵(1,1)~(x,y)的和
{
    long long ans=0;
    int i=x;
    while(i>0)
    {
        int j=y;
        while(j>0)
        {
            ans+=c[i][j];
            j-=lowbit(j);
        }
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    int x,y,x1,y1,m;
    long long k;
    while(1)
    {
        scanf("%d",&m);
        if(m==0)    {scanf("%d",&x);memset(c,0,sizeof(c));}
        if(m==1)
        {
            scanf("%d%d%lld",&x,&y,&k);
            update(x+1,y+1,k);
        }
        if(m==2)
        {
            scanf("%d%d%d%d",&x,&y,&x1,&y1);
            x++;y++;x1++;y1++;
            ans=sum(x1,y1)-sum(x-1,y1)-sum(x1,y-1)+sum(x-1,y-1);	//二维前缀和
            printf("%lld\n",ans);
        }
        if(m==3) break;
    } 
    return 0;
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值