上帝造题的七分钟 [Tyvj 1716]

2 篇文章 0 订阅
1 篇文章 0 订阅

题目地址请点击


上帝造题的七分钟


Background

裸体就意味着身体。


Description

“第一分钟,X说,要有矩阵,于是便有了一个里面写满了 0 n×m 矩阵。
第二分钟,L说,要能修改,于是便有了将左上角为 (a,b) ,右下角为 (c,d) 的一个矩形区域内的全部数字加上一个值的操作。
第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。
第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。
第五分钟,和雪说,要有耐心,于是便有了时间限制。
第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
——《上帝造裸题的七分钟》
所以这个神圣的任务就交给你了。


Input

输入数据的第一行为 X n m ,代表矩阵大小为 n×m
从输入数据的第二行开始到文件尾的每一行会出现以下两种操作:
L a b c d delta —— 代表将 (a,b) , (c,d) 为顶点的矩形区域内的所有数字加上 delta
k a b c d —— 代表求 (a,b) , (c,d) 为顶点的矩形区域内所有数字的和。

请注意, k 为小写。


Output

针对每个 k 操作,在单独的一行输出答案。


Sample Input

X 4 4
L 1 1 3 3 2
L 2 2 4 4 1
k 2 2 3 3


Sample Output

12


Hint

对于 10% 的数据, 1n16 , 1m16 , 操作不超过 200 个.
对于 60% 的数据, 1n512 , 1m512 .
对于 100% 的数据, 1n2048 , 1m2048 , 1delta500 , 操作不超过 200000 个,保证运算过程中及最终结果均不超过32位带符号整数类型的表示范围。
by XLk


Solution

二维树状数组,区间修改+区间查询模板题。
学到了神犇Cai的读入优化,感觉大神的代码就是不同,读入优化都比我快。


Code

#include <iostream>
#include <cstdio>

using namespace std;

int n,m,num,ch[100];

char str;

int bit1[2059][2059];
int bit2[2059][2059];
int bit3[2059][2059];
int bit4[2059][2059];

inline void in(int &ans){
    ans=0;
    int flag=1;
    char x=getchar();
    while((x<'0'||x>'9')&&x!='-')x=getchar();
    if(x=='-'){flag=-1;x=getchar();}
    while(x>='0'&&x<='9'){ans=ans*10+x-'0';x=getchar();}
    ans*=flag;
}

inline void add(int x,int y,int z,int array[2059][2059]){
    for(int i=x;i<=n;i+=(i&-i))
        for(int j=y;j<=m;j+=(j&-j))
            array[i][j]+=z;
}

inline int get_sum(int x,int y,int array[2059][2059]){
    int tmp=0;
    for(int i=x;i;i-=(i&-i))
        for(int j=y;j;j-=(j&-j))
            tmp+=array[i][j];
    return tmp;
}

inline int sum(int x,int y){
    int tmp=0;
    tmp+=get_sum(x,y,bit1)*x*y;
    tmp-=get_sum(x,y,bit2)*x;
    tmp-=get_sum(x,y,bit3)*y;
    tmp+=get_sum(x,y,bit4);
    return tmp;
}

inline void out(int k){
    if(k<0){putchar('-');k=-k;}
    if(k==0){putchar('0');putchar(10);return;}
    while(k>0)ch[++num]=k%10,k/=10;
    while(num)putchar(ch[num--]+48);
    putchar(10);
}

int main(){

    getchar();getchar();in(n);in(m);

    while((str=getchar())!=-1){

        if(str=='L'){
            int a,b,c,d,delta;
            in(a);in(b);in(c);in(d);in(delta);

            add(a,b,delta,bit1);add(a,d+1,-delta,bit1);
            add(c+1,b,-delta,bit1);add(c+1,d+1,delta,bit1);

            add(a,b,delta*(b-1),bit2);add(a,d+1,-delta*(d),bit2);
            add(c+1,b,-delta*(b-1),bit2);add(c+1,d+1,delta*(d),bit2);

            add(a,b,delta*(a-1),bit3);add(a,d+1,-delta*(a-1),bit3);
            add(c+1,b,-delta*(c),bit3);add(c+1,d+1,delta*(c),bit3);

            add(a,b,delta*(a-1)*(b-1),bit4);add(a,d+1,-delta*(a-1)*(d),bit4);
            add(c+1,b,-delta*(c)*(b-1),bit4);add(c+1,d+1,delta*(c)*(d),bit4);
        }

        else{
            int a,b,c,d;
            in(a);in(b);in(c);in(d);
            out(sum(c,d)+sum(a-1,b-1)-sum(c,b-1)-sum(a-1,d));
        }

    }

    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值