“第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵。
第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作。
第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。
第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。
第五分钟,和雪说,要有耐心,于是便有了时间限制。
第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
——《上帝造裸题的七分钟》
所以这个神圣的任务就交给你了。
输入数据的第一行为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为小写。
//by 减维
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<bitset>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int lowbit(int x){return x&(-x);}
struct tree{
int sum[2050][2050];
void change(int x,int y,int v)
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=m;j+=lowbit(j))
sum[i][j]+=v;
}
int ask(int x,int y)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
ans+=sum[i][j];
return ans;
}
}t1,t2,t3,t4;
int calc(int x,int y)
{
return t1.ask(x,y)*(x+1)*(y+1)+t4.ask(x,y)-t2.ask(x,y)*(y+1)-t3.ask(x,y)*(x+1);
}
int main()
{
char op[5];
scanf("%s%d%d",op,&n,&m);
int a,b,c,d,val;
while(~scanf("%s",op)){
if(op[0]==‘L‘){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&val);
t1.change(a,b,val); t1.change(c+1,d+1,val); t1.change(a,d+1,-val); t1.change(c+1,b,-val);
t2.change(a,b,val*a); t2.change(c+1,d+1,val*(c+1)); t2.change(a,d+1,-val*a); t2.change(c+1,b,-val*(c+1));
t3.change(a,b,val*b); t3.change(c+1,d+1,val*(d+1)); t3.change(a,d+1,-val*(d+1)); t3.change(c+1,b,-val*b);
t4.change(a,b,val*a*b);t4.change(c+1,d+1,val*(c+1)*(d+1));t4.change(a,d+1,-val*a*(d+1));t4.change(c+1,b,-val*(c+1)*b);
}else{
scanf("%d%d%d%d",&a,&b,&c,&d);
printf("%d\n",calc(c,d)-calc(c,b-1)-calc(a-1,d)+calc(a-1,b-1));
}
}
return 0;
}