Luogu4514 上帝造题的七分钟
Luogu4514 上帝造题的七分钟
填坑填坑。。。
二维树状数组
区间加区间求和,和一维一样需要差分。
设差分后矩阵变成\(c\)。
\[s_{x,y}= \sum_{i=1}^x \sum_{j=1}^y \sum_{p=1}^i \sum_{q=1}^j c_{p,q}\\
=\sum_{i=1}^x \sum_{j=1}^y (x-i+1)(y-j+1) c_{i,j}\\
=\sum_{i=1}^x \sum_{j=1}^y (xy-xj+x-yi+ij-i+y-j+1)c_{i,j}\\
=\sum_{i=1}^x \sum_{j=1}^y (xy+x+y+1)c_{i,j}-(y+1)i \times c_{i,j}-(x+1)j \times c_{i,j}+ij \times c_{i,j}
\]
维护\(c_{i,j},i \times c_{i,j} ,j \times c_{i,j} , ij \times c_{i,j}\)前缀和即可。
\(Code:\)
#include<iostream>
#include<algorithm>
#include<cstdio>
#define N 2050
#define lowbit(x) (x & (-x))
#define ll long long
using namespace std;
char X[5];
int n,m,a,b,c,d,z;
struct node
{
int a,b,c,d;
node (int A=0,int B=0,int C=0,int D=0)
{
a=A,b=B,c=C,d=D;
}
void add(int z1,int z2,int z3,int z4)
{
a+=z1,b+=z2,c+=z3,d+=z4;
}
}hoho[N][N];
void update(int x,int y,int z)
{
int z2=z*x,z3=z*y,z4=z*x*y;
for (int i=x;i<=n;i+=lowbit(i))
for (int j=y;j<=m;j+=lowbit(j))
hoho[i][j].add(z,z2,z3,z4);
}
int calc(int x,int y)
{
int ans=0;
for (int i=x;i;i-=lowbit(i))
for (int j=y;j;j-=lowbit(j))
ans+=hoho[i][j].a*(x*y+x+y+1)-hoho[i][j].b*(y+1)-hoho[i][j].c*(x+1)+hoho[i][j].d;
return ans;
}
int main()
{
scanf("%s%d%d",X,&n,&m);
while (scanf("%s%d%d%d%d",X,&a,&b,&c,&d)!=EOF)
{
switch (X[0])
{
case 'L':
scanf("%d",&z);
update(a,b,z),update(a,d+1,-z),update(c+1,b,-z),update(c+1,d+1,z);
break;
case 'k':
printf("%d\n",calc(c,d)-calc(a-1,d)-calc(c,b-1)+calc(a-1,b-1));
break;
}
}
return 0;
}