P4514 上帝造题的七分钟

题目描述

“第一分钟,X说,要有矩阵,于是便有了一个里面写满了00的n×mn×m矩阵。

第二分钟,L说,要能修改,于是便有了将左上角为(a,b)(a,b),右下角为(c,d)(c,d)的一个矩形区域内的全部数字加上一个值的操作。

第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。

第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。

第五分钟,和雪说,要有耐心,于是便有了时间限制。

第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。

第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”

——《上帝造裸题的七分钟》

所以这个神圣的任务就交给你了。

二维树状数组裸题。

定义二维差分数组:

\[d(i)(j)=a(i)(j)-a(i-1)(j)-a(i)(j-1)+a(i-1)(j-1)
\]

如何维护\(1,1\)到\(i,j\)的二维前缀和?

\[sum(x)(y)=\sum_{i=1}^x\sum_{j=1}^y\sum_{k=1}^i\sum_{l=1}^jd(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】 上帝造题的七分钟的更多相关文章

  1. 模板:二维树状数组 【洛谷P4054】 [JSOI2009]计数问题

    P4054 [JSOI2009]计数问题 题目描述 一个n*m的方格,初始时每个格子有一个整数权值.接下来每次有2种操作: 改变一个格子的权值: 求一个子矩阵中某种特定权值出现的个数. 输入输出格式 ...

  2. 洛谷 P4514 上帝造题的七分钟 解题报告

    P4514 上帝造题的七分钟 题目背景 裸体(裸题)就意味着身体(神题). 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了\(0\)的\(n \times m\)矩阵. 第二 ...

  3. 洛谷P4514 上帝造题的七分钟

    P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了000的n×mn×mn×m矩阵. 第二分钟,L说,要能修改,于是便有 ...

  4. 洛谷P4145 上帝造题的七分钟2/花神游历各国 [树状数组,并查集]

    题目传送门 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是 ...

  5. 洛谷P4145——上帝造题的七分钟2 / 花神游历各国

    题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...

  6. 洛谷P4145上帝造题的七分钟——区间修改

    题目:https://www.luogu.org/problemnew/show/P4145 区间开平方,可以发现其实开几次就变成1,不需要开了,所以标记一下,每次只去开需要开的地方: 原来写的并查集 ...

  7. 洛谷 P4145 上帝造题的七分钟2 / 花神游历各国

    洛谷 这题就是区间开根号,区间求和.我们可以分块做. 我们记布尔数组vis[i]表示第i块中元素是否全部为1. 因为显然当一个块中元素全部为1时,并不需要对它进行根号操作. 我们每个块暴力开根号,因为 ...

  8. 洛谷P4145 上帝造题的七分钟2 / 花神游历各国(重题:洛谷SP2713 GSS4 - Can you answer these queries IV)

    题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段 ...

  9. 洛谷P4054 [JSOI2009]计数问题(二维树状数组)

    题意 题目链接 Sol 很傻x的题.. c才100, n, m才300,直接开100个二维树状数组就做完了.. #include<bits/stdc++.h> using namespac ...

  10. 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]

    题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...

随机推荐

  1. javascript一些小的注意点

    try...catch 可以测试代码中的错误.try 部分包含需要运行的代码,而 catch 部分包含错误发生时运行的代码. 当try { 里面的代码 出现错误了 }catch(e){ 才执行下面的c ...

  2. KVO键值监听

    KVO 键值监听:当我想知道一个对象的属性是否发生改变的时候 做出响应,就需要添加监听keypath 和 key的区别keypath会自动寻找子类的属性key只会寻找当前类的属性添加键值监听[pers ...

  3. PHP函数(五)-回调函数

    回调函数是指调用函数的时候将另一个函数作为参数传递到调用的函数中,而不是传递一个普通的变量作为参数 使用回调函数是为了可以将一段自己定义的功能传到函数内部使用 声明回调函数的方法 变量函数声明 < ...

  4. xcode 编译错误找不到 libz.dylib

    图片对应的是libxml2.dylib  (libz.dylib 遇到的编译错误跟这个类似) 解决方法是在引入库的地方调整原先 比如libz.dylib 的目录: ================== ...

  5. Django之时区

    在settings.py中修改如下配置: TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False 这样在m ...

  6. 【转】如何使用Java、Servlet创建二维码

    归功于智能手机,QR码逐渐成为主流,它们正变得越来越有用.从候车亭.产品包装.家装卖场.汽车到很多网站,都在自己的网页集成QR码,让人们快速找到它们.随着智能手机的用户量日益增长,二维码的使用正在呈指 ...

  7. JSON 解析出错问题

    从 PHP 返回一段 JSON 数据给前台页面,但使用 eval 和 JSON.parse 解析都出错. 在网上那上在线的 json 解析工具解析都正确. 于是一段段删除测试,最终发现问题出在 \r\ ...

  8. 如何设置Win10文件资源管理器默认打开“这台电脑”

    摘录自:http://www.ithome.com/html/win10/126066.htm

  9. WebView三个方法区别(解决乱码问题)

    最近使用WebView加载中文网页的时候出现乱码问题,网上整理下基本解决方法: 其实我发现这不管是在线还是离线显示都可以使用LoadUrl方法!联网时好像是默认utf-8,离线读取本地时需要设置默认编 ...

  10. JQuery利用css()修改样式后 hover失效的解决办法

    执行完代码后发现写在样式表中的hover效果失效,改了好几遍差点重新写函数,后来发现很简单,是优先级的问题,css()中的内容覆盖了之前的样式 只需要在样式后写!important即可解决! .fil ...