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;
}
posted @ 2020-12-14 19:30  GK0328  阅读(54)  评论(0编辑  收藏  举报