CDQ求子矩阵的和
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
Input
第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束
Output
对于每个输入2,输出一行,即输入2的答案
Sample Input
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
HINT
保证答案不会超过int范围
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map> using namespace std; #define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(a,val) memset(a,val,sizeof(a))
#define PI acos(-1.0) const double EXP = 1e-;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const double DINF = 0xffffffffffff;
const int mod = 1e9+;
const int N = 2e6+; struct node{
int typ; //类型
int x,y;
int id; //记录输入相对位置
int val;
int pos; //输出答案用
}a[N],tmp[N]; int n,w,tot;
int ans[]; //答案数组 bool cmp(node a,node b){
if(a.x==b.x&&a.y==b.y)
return a.id<b.id;
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
} int tree[N]; //tree数组按二进制存,根据n的末尾0的个数存取,树状数组 int lowbit(int x)
{
return x&(-x);
} int Query(int x) //返回1到x的前缀和
{
int res=;
while(x)
{
res+=tree[x];
x-=lowbit(x);
}
return res;
} void Add(int x,int v) //实现a[x]+v;
{
while(x<=n) //注意这里是小于等于k,还是n,k是数据范围
{
tree[x]+=v;
x+=lowbit(x);
}
} void clearr(int x){
while(x<=n){
if(tree[x]==)
break;
tree[x]=;
x+=lowbit(x);
}
} void cdq(int l,int r){
if(l>=r)
return ;
int mid=l+r>>;
cdq(l,mid);
cdq(mid+,r);
int p=l,q=mid+,k=l;
while(p<=mid&&q<=r){
if(a[p].id<=a[q].id){
if(a[p].typ==)
Add(a[p].y,a[p].val);
tmp[k++] = a[p++];
}
else{
if(a[q].typ==)
ans[a[q].pos]+=Query(a[q].y)*a[q].val;
tmp[k++] = a[q++];
}
}
while(p<=mid){
if(a[p].typ==)
Add(a[p].y,a[p].val);
tmp[k++]=a[p++];
}
while(q<=r){
if(a[q].typ==)
ans[a[q].pos]+=Query(a[q].y)*a[q].val;
tmp[k++]=a[q++];
}
for(int i=l;i<=r;i++){
clearr(a[i].y);
a[i]=tmp[i];
}
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
std::ios::sync_with_stdio(false);
int s;
scanf("%d%d",&s,&n);
int opt,x,y,val,x1,x2,y1,y2;
tot=;
int m=;
while(~scanf("%d",&opt)){
if(opt==)
break;
if(opt==){
scanf("%d%d%d",&x,&y,&val);
a[++m]=node{,x,y,m,val,};
}
else{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
++tot;
//比x2,y2小的都加上,val赋值1
a[++m]=node{,x2,y2,m,,tot};
//因为他是中间矩阵,而我们加是1~x,1~y的加,所以多出来的要赋值成-1,来减掉,val赋值-1
a[++m]=node{,x2,y1-,m,-,tot};
a[++m]=node{,x1-,y2,m,-,tot};
//这里多减了一次,要加回来,val赋值1
a[++m]=node{,x1-,y1-,m,,tot}; ans[tot]+=(x2-x1+)*(y2-y1+)*s; //答案赋初值
}
}
sort(a+,a++m,cmp);
cdq(,m);
for(int i=;i<=tot;i++)
printf("%d\n",ans[i]);
return ;
}
CDQ求子矩阵的和的更多相关文章
- ACM 中 矩阵数据的预处理 && 求子矩阵元素和问题
我们考虑一个$N\times M$的矩阵数据,若要对矩阵中的部分数据进行读取,比如求某个$a\times b$的子矩阵的元素和,通常我们可以想到$O(ab)$的遍历那个子矩阵,对它的各 ...
- bzoj 3295 CDQ求动态逆序对
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk mak ...
- [ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵
https://www.luogu.org/problemnew/show/P1169 第一次听说到这种dp的名称叫做悬线法,听起来好厉害 题意是求一个矩阵内的最大01交错子矩阵,开始想的是dp[20 ...
- P2258子矩阵
传送 一道看起来就很暴力的题. 这道题不仅暴力,还要用正确的姿势打开暴力. 因为子矩阵的参数有两个,一个行一个列(废话) 我们一次枚举两个参数很容易乱对不对?所以我们先枚举行,再枚举列 枚举完行,列, ...
- dp例题03. 最大子矩阵和
题目Description: 给出一个矩阵, 求子矩阵(可以是其本身)数之和的最大值 Input: 第一行 为行数n和列数m (n≤500, m≤500) 接下来为一个n行m列的矩阵 (每 ...
- bzoj1176 2683
我的第一道cdq分治题清明做了一下cdq分治的几道题,感觉这个东西实在是太厉害了离线大法好!关于几个经典的非数据结构做法具体可以看xhr神犇2013年的论文应用cdq分治的前提条件是不强制在线,修改操 ...
- hdu2888 二维RMQ
Check Corners Time Limit: 2000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- Java知识点总结(不定时更新)
1.基于分代的垃圾收集算法 设计思路:把对象按照寿命长短来分组,分为年轻代和年老代,新创建的对象被分在年轻代,如果对象经过几次回收后仍然存活,那么再把这个对象划分到年老代.年老代的收集频率不像年轻代那 ...
- FZU 1018 枚举dp
题意 给出一个数字组成的立方体 在其中选取一个体 使这个体中的数字之和最小 不可以不选 fzu的题目分类动态规划里面不是按难度排得 是按照题号..记得以前做题碰到过算 矩阵里面求子矩阵的最大和的 不会 ...
随机推荐
- mysql分组统计后将结果顺序排列(union实现)
工作中用到统计12月份通话记录,统计号码拨打次数,但是问题出在一个号码可以拨打多次,每次可能接通也可能不接通,如果用主叫号码caller字段group by分组后count(*)统计数目,这样会导致不 ...
- java 如何重写equal 和hashcode方法(最佳实践)
先看完理解这篇:Java hashCode() 和 equals()的若干问题解答 实现高质量的equals方法的诀窍包括 使用==操作符检查“参数是否为这个对象的引用”: 使用instanceof操 ...
- java中的四种引用方式(强引用,软引用,弱引用,虚引用)
java内存管理主要有内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象. java中对象的引用主要有四种:强引用,软引用,弱引用,虚引用. Java中提供这四种引 ...
- HTTPS和HTTP的区别,http协议的特征
http协议传输的数据都是没有经过加密的,也就是明文,所以http用于传输数据并不安全.而https是是使用了ssl(secure socket layer)协议+http协议构成的可加密传输,身份认 ...
- 神经网络中的反向传播法--bp【转载】
from: 作者:Charlotte77 出处:http://www.cnblogs.com/charlotte77/ 一文弄懂神经网络中的反向传播法——BackPropagation 最近在看深度学 ...
- python之模块导入和包
一.何为模块 1.一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 2.模块目的和函数,对象等一样,是为了代码的复用性而存在的.即一个py程序写了很多功能,也可 ...
- rev 反向输出文件内容
1.命令功能 rev 按行反向输出文件内容 2.语法格式 rev file 3.使用范例 [root@localhost ~]# echo {a..k} >> test [root@lo ...
- GUI学习之二十四——QDialog学习总结
今天学习对话框输入控件的基类(QDialog). 一.描述 是对话类窗口(字体框.颜色选择.文件选择框等)的基类. 对话框窗口是顶级窗口(就是说不包含于哪个父类的显示界面里),主要用于短期任务和与用户 ...
- VMware使用自带工具vmware-vdiskmanager精简占用磁盘空间
https://blog.csdn.net/xcl113/article/details/50715943 vmware-vdiskmanager压缩磁盘大小,验证有效 一 .sudo apt-get ...
- easyuUI实现客户分页显示逻辑分析
页面 前端 前端easyUI,自带分页功能,添加pagination属性 前端会传给后端两个属性: page:当前页码 rows:每页显示记录数 后端 接收page和rows参数 根据参数分页查询 获 ...