【树状数组】BZOJ3132 上帝造题的七分钟

3132: 上帝造题的七分钟

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1004  Solved: 445
[Submit][Status][Discuss]

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

对于100%的数据,1 ≤ n ≤ 2048, 1 ≤ m ≤ 2048, 1 ≤ abs(delta) ≤ 500,操作不超过200000个,保证运算过程中及最终结果均不超过32位带符号整数类型的表示范围。

题解

二维树状数组区间修改区间查询。。。

公式其实挺好推的,从一维扩展道二维就行。。。

反正就是维护下v[i][j]v[i][j]*iv[i][j]*jv[i][j]*i*j 的前缀和

代码

//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
",calc(c,d)-calc(c,b-1)-calc(a-1,d)+calc(a-1,b-1));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/rir1715/p/8006655.html