Luogu P4514(树状数组区间查询区间修改)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25576697/article/details/81806530

题目描述

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

输入输出格式

输入格式:

输入数据的第一行为X n m,代表矩阵大小为 n×mn×m 。
从输入数据的第二行开始到文件尾的每一行会出现以下两种操作:

  • L a b c d delta —— 代表将 (a,b),(c,d)(a,b),(c,d) 为顶点的矩形区域内的所有数字加上delta。
  • k a b c d —— 代表求 (a,b),(c,d)(a,b),(c,d) 为顶点的矩形区域内所有数字的和。

请注意, kk 为小写。

输出格式:

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

输入输出样例

输入样例#1: 复制

扫描二维码关注公众号,回复: 3162425 查看本文章
X 4 4
L 1 1 3 3 2
L 2 2 4 4 1
k 2 2 3 3

输出样例#1: 复制

12

说明

对于10%的数据, 1 ≤ n ≤ 16, 1 ≤ m ≤ 161≤n≤16,1≤m≤16 , 操作不超过200个.
对于60%的数据, 1 ≤ n ≤ 512, 1 ≤ m ≤ 5121≤n≤512,1≤m≤512 .
对于100%的数据, 1 ≤ n ≤ 2048, 1 ≤ m ≤ 2048, -500 ≤ delta ≤ 5001≤n≤2048,1≤m≤2048,−500≤delta≤500 ,操作不超过200000个,保证运算过程中及最终结果均不超过32位带符号整数类型的表示范围。
by XLk

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

需要差分。

查询[1,1]到[x,y]的原式为整理后再整理一下得到

所以需要维护4个树状数组。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn = 2050;
int c1[maxn][maxn],c2[maxn][maxn],c3[maxn][maxn],c4[maxn][maxn];
int n,m;
void update(int c[][maxn],int x,int y,int w)
{
    int y1;
    while(x<=n)
    {
        y1 = y;
        while(y1<=m)
        {
            c[x][y1]+=w;
            y1 += y1&(-y1);
        }
        x += x&(-x);
    }
}
int sum(int c[][maxn],int x,int y)
{
    int ans = 0;
    int y1;
    while(x>0)
    {
        y1 = y;
        while(y1>0)
        {
            ans +=c[x][y1];
            y1 -= y1&(-y1);
        }
        x -= x&(-x);
    }
    return ans;
}
void add(int x,int y,int w)
{
    update(c1,x,y,w);
    update(c2,x,y,x*w);
    update(c3,x,y,y*w);
    update(c4,x,y,x*y*w);
}
int getsum(int x,int y)
{
    return (x*y+x+y+1)*sum(c1,x,y) - (1+y)*sum(c2,x,y) - (1+x)*sum(c3,x,y) + sum(c4,x,y);
}
int read()
{
    int sign=1,res=0;
    char c;
    while((c=getchar())<48||c>57)
        if(c=='-')
            sign=-1;
    if(sign)
        res=c-48;
    while((c=getchar())>=48&&c<=57)
        res=res*10+c-48;
    return res*sign;
}
int main()
{
    scanf("X %d %d",&n,&m);
    char op[3];
    int x1,x2,y1,y2;
    int w;
    while(~scanf("%s",&op))
    {
        x1 = read();
        y1 = read();
        x2= read();
        y2= read();
        if(op[0]=='L')
        {
            w= read();
            add(x1,y1,w);
            add(x2+1,y1,-w);
            add(x1,y2+1,-w);
            add(x2+1,y2+1,w);
        }
        else
        {
            printf("%d\n",getsum(x2,y2) - getsum(x2,y1-1) - getsum(x1-1,y2) + getsum(x1-1,y1-1));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/81806530