二维树状数组总结&&【洛谷P4514】 上帝造题的七分钟
P4514 上帝造题的七分钟
题目描述
“第一分钟,X说,要有矩阵,于是便有了一个里面写满了00的n×mn×m矩阵。
第二分钟,L说,要能修改,于是便有了将左上角为(a,b)(a,b),右下角为(c,d)(c,d)的一个矩形区域内的全部数字加上一个值的操作。
第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。
第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。
第五分钟,和雪说,要有耐心,于是便有了时间限制。
第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
——《上帝造裸题的七分钟》
所以这个神圣的任务就交给你了。
二维树状数组裸题。
定义二维差分数组:
\]
如何维护\(1,1\)到\(i,j\)的二维前缀和?
=\sum_{i=1}^x\sum_{j=1}^yd(i)(j)*(x+1-i)*(y+1-i)\\
=(x+1)*(y+1)*\sum_{i=1}^x\sum_{j=1}^yd(i)(j)-(y+1)\sum_{i=1}^x\sum_{j=1}^yd(i)(j)*i\\-(x+1)*\sum_{i=1}^x\sum_{j=1}^y*j+\sum_{i=1}^x\sum_{j=1}^y*d(i)(j)*i*j
\]
按照上述式子维护四个前缀和数组即可。
具体操作:
code:
void add(int posx,int posy,int k){
for(int i=posx;i<=n;i+=(i&-i)){
for(int j=posy;j<=m;j+=(j&-j)){
sum1[i][j]+=k;
sum2[i][j]+=k*posx;
sum3[i][j]+=k*posy;
sum4[i][j]+=k*posx*posy;
}
}
}
int query(int posx,int posy){
int re=0;
for(int i=posx;i>=1;i-=(i&-i)){
for(int j=posy;j>=1;j-=(j&-j)){
re+=((posx+1)*(posy+1))*sum1[i][j]-(posy+1)*sum2[i][j]-(posx+1)*sum3[i][j]+sum4[i][j];
}
}
return re;
}
void add_wx(int x1,int x2,int y1,int y2,int k){
add(x1,y1,k);
add(x1,y2+1,-k);
add(x2+1,y1,-k);
add(x2+1,y2+1,k);
}
int query_wx(int x1,int x2,int y1,int y2){
return query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1);
}
针对本题:
code:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
using namespace std;
const int wx=3017;
inline int read(){
int sum=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
return sum*f;
}
int sum1[wx][wx];
int sum2[wx][wx];
int sum3[wx][wx];
int sum4[wx][wx];
int n,m;
char opt[4];
/*
d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]
sum1[i][j]-->d[i][j]
sum2[i][j]-->d[i][j]*i
sum3[i][j]-->d[i][j]*j
sum4[i][j]-->d[i][j]*i*j
sum[x1][y1][x2][y2]=(x+1)*(y+1)*sum1[i][j]-(y+1)*sum2[i][j]-(x+1)*sum3[i][j]+sum4[i][j]。
*/
void add(int posx,int posy,int k){
for(int i=posx;i<=n;i+=(i&-i)){
for(int j=posy;j<=m;j+=(j&-j)){
sum1[i][j]+=k;
sum2[i][j]+=k*posx;
sum3[i][j]+=k*posy;
sum4[i][j]+=k*posx*posy;
}
}
}
int query(int posx,int posy){
int re=0;
for(int i=posx;i>=1;i-=(i&-i)){
for(int j=posy;j>=1;j-=(j&-j)){
re+=((posx+1)*(posy+1))*sum1[i][j]-(posy+1)*sum2[i][j]-(posx+1)*sum3[i][j]+sum4[i][j];
}
}
return re;
}
void add_wx(int x1,int x2,int y1,int y2,int k){
add(x1,y1,k);
add(x1,y2+1,-k);
add(x2+1,y1,-k);
add(x2+1,y2+1,k);
}
int query_wx(int x1,int x2,int y1,int y2){
return query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1);
}
int main(){
scanf("%s");
n=read(); m=read();
while(scanf("%s",opt+1)!=EOF){
if(opt[1]=='L'){
int x,y,z,c,k;
x=read(); y=read(); z=read(); c=read(); k=read();
add_wx(x,z,y,c,k);
}
else{
int x,y,z,c;
x=read(); y=read(); z=read(); c=read();
printf("%d\n",query_wx(x,z,y,c));
}
}
return 0;
}
二维树状数组总结&&【洛谷P4514】 上帝造题的七分钟的更多相关文章
- 模板:二维树状数组 【洛谷P4054】 [JSOI2009]计数问题
P4054 [JSOI2009]计数问题 题目描述 一个n*m的方格,初始时每个格子有一个整数权值.接下来每次有2种操作: 改变一个格子的权值: 求一个子矩阵中某种特定权值出现的个数. 输入输出格式 ...
- 洛谷 P4514 上帝造题的七分钟 解题报告
P4514 上帝造题的七分钟 题目背景 裸体(裸题)就意味着身体(神题). 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了\(0\)的\(n \times m\)矩阵. 第二 ...
- 洛谷P4514 上帝造题的七分钟
P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了000的n×mn×mn×m矩阵. 第二分钟,L说,要能修改,于是便有 ...
- 洛谷P4145 上帝造题的七分钟2/花神游历各国 [树状数组,并查集]
题目传送门 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是 ...
- 洛谷P4145——上帝造题的七分钟2 / 花神游历各国
题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...
- 洛谷P4145上帝造题的七分钟——区间修改
题目:https://www.luogu.org/problemnew/show/P4145 区间开平方,可以发现其实开几次就变成1,不需要开了,所以标记一下,每次只去开需要开的地方: 原来写的并查集 ...
- 洛谷 P4145 上帝造题的七分钟2 / 花神游历各国
洛谷 这题就是区间开根号,区间求和.我们可以分块做. 我们记布尔数组vis[i]表示第i块中元素是否全部为1. 因为显然当一个块中元素全部为1时,并不需要对它进行根号操作. 我们每个块暴力开根号,因为 ...
- 洛谷P4145 上帝造题的七分钟2 / 花神游历各国(重题:洛谷SP2713 GSS4 - Can you answer these queries IV)
题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...
- 洛谷P4054 [JSOI2009]计数问题(二维树状数组)
题意 题目链接 Sol 很傻x的题.. c才100, n, m才300,直接开100个二维树状数组就做完了.. #include<bits/stdc++.h> using namespac ...
- 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]
题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...
随机推荐
- Oracle 高可用作业测试
1.RAC 是一种: A 分布式数据库B 内存共享多节点数据库C 能够保护数据安全的架构 2.RAC 和CRS 的区别是: A 前者表示一种架构,后者是一套软件B 前者表示一套软件,后者是一种架构 C ...
- nginx for windows之负载均衡
1.编辑c:\nginx\conf\nginx.conf 添加以下内容: #user nobody; #启动进程worker_processes 1; #全局错误日志及PID文件err ...
- Android 4学习(6):概述 - 深入了解Android Activity
参考:<Professional Android 4 Application Development> 深入了解Android Activity 每一个Android Activity都对 ...
- java 多线程系列---JUC原子类(四)之AtomicReference原子类
AtomicReference介绍和函数列表 AtomicReference是作用是对"对象"进行原子操作. AtomicReference函数列表 // 使用 null 初始 ...
- struts2学习笔记(4)接收参数
①用action属性接收 登录界面例子 在webroot下创建login.jsp和success.jsp login.jsp中加入表单: <form action="LoginActi ...
- JavaScript去除空格的三种方法(正则/传参函数/trim)
方法一: 个人认为最好的方法.采用的是正则表达式,这是最核心的原理. 其次.这个方法使用了JavaScript 的prototype 属性 其实你不使用这个属性一样可以用函数实现.但这样做后用起来比较 ...
- Lucene源码解析--Analyzer之Tokenizer
Analyzer包含两个核心组件,Tokenizer以及TokenFilter.两者的区别在于,前者在字符级别处理流,而后者则在词语级别处理流.Tokenizer是Analyzer的第一步,其构造函数 ...
- 请用fontAwesome代替网页icon小图标(转)
1. 引言 网页小图标到处可见,如果一个网页都是干巴巴的文字和图片,而没有小图标,会显得非常简陋.下面的小图标,你是不是会经常用到? 你可能说——“我们用的都是彩色的,不是黑白的”——别着急,下面会讲 ...
- JSON数据格式简介
---------------siwuxie095 JSON 简介 JSON:JavaScript 对象表示法(JavaScript Objec ...
- 简单的jQuery前端验证码校验
简单的jQuery前端验证码校验2 html; <!DOCTYPE html> <html lang="zh-cn"> <head> <m ...