[luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)
P4514 上帝造题的七分钟
题目背景
裸体就意味着身体。
题目描述
“第一分钟,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为小写。
输出格式:
针对每个k操作,在单独的一行输出答案。
输入输出样例
输入样例#1: 复制
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 ≤ 16, 操作不超过200个.
对于60%的数据,1 ≤ n ≤ 512, 1 ≤ m ≤ 512.
对于100%的数据,1 ≤ n ≤ 2048, 1 ≤ m ≤ 2048, -500 ≤ delta ≤ 500,操作不超过200000个,保证运算过程中及最终结果均不超过32位带符号整数类型的表示范围。
by XLk
题解
想写二维线段树。
然而讨论里说卡掉了空间了。
那就硬着头皮写二维树状数组吧。
二维树状数组教做人系列。
对于一维的树状数组,我们知道区间加和区间求和是需要差分并维护两个树状数组的。(不会的可以去用树状数组写一下x谷的线段树模板1)
这个对于二维树状数组同样适用。
那么我们假设\(sum[i][j]\)为差分数组。
\(sum[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]\)。
为什么要这么假设呢?
因为这样我们可以发现
对于点\((x,y)\)的值就是
\(\sum_{i=1}^x\sum_{j=1}^y\sum_{h=1}^i\sum_{k=1}^j sum[h][k]\)
根据每一次的求值,我们发现以\((x,y)\)为结尾的矩阵,每个差分数组出现的次数为
\(\sum_{i=1}^x\sum_{j=1}^y sum[i][j]*(x-i+1)*(y-j+1)\)
是不是会发现开始变得和一维树状数组求法一样了。
接下来让我们把这个公式拆开食用。
\(\sum_{i=1}^x\sum_{j=1}^y sum[i][j]*(xy+x+y+1)-sum[i][j]*i(y+1)-sum[i][j]*j(x+1)+sum[i][j]*i*j\)
发现只要维护\(sum[i][j],sum[i][j]*i,sum[i][j]*j,sum[i][j]*i*j\)四个树状数组了。
好现在考虑加值。给\((2,2),(3,3)\)的矩阵加上值。
在差分数组里面就是这样的
0 0 0 0 0
0 + 0 - 0
0 0 0 0 0
0 - 0 + 0
就等于正常数组里面的
0 0 0 0 0
0 + + 0 0
0 + + 0 0
0 0 0 0 0
即在给\((x_1,y_1),(x_2,y_2)\)加值时。我们需要给\((x_1,y_1),(x_2+1,y_2+1)\)加,\((x_1,y_2+1),(x_2+1,y_1)\)减。
因为统计数组时,点\((i,j)\)的值为以\((i,j)\)为右下角,\((1,1)\)为左上角的差分矩阵的和。
题解
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
struct node{
int t[2050][2050];
void add(int x,int y,int v){
for(int i=x;i<=n;i+=(i&(-i)))
for(int j=y;j<=m;j+=(j&(-j)))
t[i][j]+=v;
}
int query(int x,int y){
int sum=0;
for(int i=x;i;i-=(i&(-i)))
for(int j=y;j;j-=(j&(-j)))
sum+=t[i][j];
return sum;
}
}Q,Qi,Qj,Qij;
void add(int x,int y,int v){
Q.add(x,y,v);Qi.add(x,y,v*x);
Qj.add(x,y,v*y);Qij.add(x,y,v*x*y);
}
int query(int x,int y){
return Q.query(x,y)*(x*y+x+y+1)-Qi.query(x,y)*(y+1)-Qj.query(x,y)*(x+1)+Qij.query(x,y);
}
int main(){
n=read();m=read();
char opt[10];
while(scanf("%s",opt)==1){
int xa=read(),ya=read(),xb=read(),yb=read();
if(opt[0]=='L'){
int v=read();
add(xa,ya,v);add(xb+1,ya,-v);
add(xb+1,yb+1,v);add(xa,yb+1,-v);
}
else {
printf("%d\n",query(xb,yb)-query(xb,ya-1)-query(xa-1,yb)+query(xa-1,ya-1));
}
}
return 0;
}
[luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)的更多相关文章
- BZOJ 3132(上帝造题的七分钟-树状数组求和+2D逆求和数组)
3132: 上帝造题的七分钟 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 46 Solved: 18[Submit][Status][Discus ...
- 【BZOJ3132】上帝造题的七分钟 [树状数组]
上帝造题的七分钟 Time Limit: 20 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description “第一分钟,X说,要有矩阵 ...
- BZOJ 3132: 上帝造题的七分钟 树状数组+差分
这个思路很巧妙啊 ~ code: #include <cstdio> #include <algorithm> #define N 2050 #define ll int #d ...
- bzoj 4822: [Cqoi2017]老C的任务【扫描线+树状数组+二维差分】
一个树状数组能解决的问题分要用树套树--还写错了我别是个傻子吧? 这种题还是挺多的,大概就是把每个矩形询问差分拆成四个点前缀和相加的形式(x1-1,y1-1,1)(x2.y2,1)(x1-1,y2,- ...
- P4514 上帝造题的七分钟——二维树状数组
P4514 上帝造题的七分钟 求的是矩阵里所有数的和: 维护四个树状数组: #include<cstdio> #include<cstring> #include<alg ...
- P4514 上帝造题的七分钟(二维树状数组)
P4514 上帝造题的七分钟 二维树状数组 差分维护区间加法,区间求和 #include<cstdio> int read(){ ,f=; ') f=f&&(c!='-') ...
- P4514 上帝造题的七分钟
P4514 上帝造题的七分钟 题意: 二维区间修改 区间查询 --- 错误日志: 写了个 4 重循环忘记调用 \(i\) Solution 二维树状数组 巨尼玛毒瘤 听说二维线段树会 \(MLE\) ...
- 洛谷 P4514 上帝造题的七分钟 解题报告
P4514 上帝造题的七分钟 题目背景 裸体(裸题)就意味着身体(神题). 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了\(0\)的\(n \times m\)矩阵. 第二 ...
- 洛谷P4514 上帝造题的七分钟
P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了000的n×mn×mn×m矩阵. 第二分钟,L说,要能修改,于是便有 ...
随机推荐
- tcpsock for Golang
前记:本文所述的 tcpsock 库托管在 Github. Golang 中的 net 标准库已对 TCP 网络编程作了简洁(却很不简单)的封装,基本上,可直接通过引用其提供的相关接口开发简易的网络应 ...
- 01 C#基础
第一天 .net平台(中国移动互联网平台): .net框架(信号塔): CLR(公共语言运行时) .Net类 库 我们使用的语言是——C# 2.解决方案项目与类的关系: 解决方案:公司 项目:部门 类 ...
- ZOJ 3911Prime Query [素数处理 + 线段树]
Time Limit: 5 Seconds Memory Limit: 196608 KBYou are given a simple task. Given a sequence A[i] with ...
- python位操作(进制)与ascii
位操作符 位操作的操作符与python的set的操作符一样.与C语言中的位操作符也是一样的. a = 60 #60的二进制为 0011 1100b = 13 #13的二进制为 00001101 c = ...
- 编写python代码获取4k高清壁纸
Huskiesir最近在研究python爬虫大约俩周了吧,由于比较懒,也没把具体研究的过程与经验写下来,实在是一大憾事.这次直接上干货,代码送给大家: import re import request ...
- vue通过路由实现页面刷新
vue 开发微信商城项目,需求如下: 购物车页面跳转到详情页,购物车页面包含了多个组件,点击结算跳转到订单页面,从订单返回时,购物车页面没有刷新,由于购物车组件之间通过bus实现事件传递,页面跳转(非 ...
- 紫书 例题8-3 UVa 1152(中途相遇法)
这道题要逆向思维, 就是求出答案的一部分, 然后反过去去寻找答案存不存在. 其实很多其他题都用了这道题目的方法, 自己以前都没有发现, 这道题专门考这个方法.这个方法可以没有一直往下求, 可以省去很多 ...
- Hadoop学习;測试;启动bug;secondary合并edits到fsimage
一个Hadoop集群拥有多个并行的计算机.用以存储和处理大规模的数据集 Hadoop强调代码向数据迁移 要执行的程序在规模上比数据小的多,更easy移动,此外通过网络移动数据比载入执行程序更花时间,这 ...
- C++基础学习教程(三)
承接上一讲. 2.7文件I/O 关于读写文件,C++中有一个专门的头文件<fstream>. 首先是读文件演示样例,例如以下: </pre><pre> /***** ...
- Linux文件系统(七)---系统调用之open操作(一)
(内核2.4.37) 一. 当我们打开一个文件的时候.须要获得文件的文件描写叙述符(前面已经说过事实上就是文件数组下标).通常是通过函数open来完毕.这个系统调用在<unistd.h>头 ...