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的题目分类动态规划里面不是按难度排得 是按照题号..记得以前做题碰到过算 矩阵里面求子矩阵的最大和的 不会 ...
随机推荐
- JSP总结(jsp/EL表达式/核心标签)
1.概念 jsp,即java Server Pages,java服务器页面. 2.简单介绍 小示例 <%@ page language="java" contentType= ...
- 洛谷 P1541 乌龟棋 & [NOIP2010提高组](dp)
传送门 解题思路 一道裸的dp. 用dp[i][j][k][kk]表示用i个1步,j个2步,k个3步,kk个4步所获得的最大价值,然后状态转移方程就要分情况讨论了(详见代码) 然后就是一开始统计一下几 ...
- FFmpeg SDK开发模型之中的一个:解码器
简单介绍 本例解说了怎样使用ffmpeg SDK解码媒体文件: 參考源代码是ffmpeg 自带的apiexample.c 一.源代码#include <stdlib.h>#include ...
- Linux基础命令四
iptables iptables -F:关闭防火墙 crontab -l查看定时任务 crontab -e :编辑定时任务 log日志相关: ls /var/log:查看日志 du -sh /v ...
- 【问题解决方案】visudo: /etc/sudoers is busy, try again later
参考链接: 博客园:visudo: /etc/sudoers is busy, try again later CSDN:Shell 获取进程号并杀掉该进程 注:找到几篇相同的参考内容,都是只有查看进 ...
- react搭建
https://juejin.im/post/5b4de4496fb9a04fc226a7af
- router4.0
https://blog.csdn.net/sinat_17775997/article/details/69218382 React Router 4.0 实现路由守卫 https://www. ...
- 前端开发HTML&css入门——伪类选择器和一些特殊的选择器
伪类和伪元素 有时候,你需要选择本身没有标签,但是仍然易于识别的网页部位,比如段落首行或鼠标滑过的连接.CSS为他们提供一些选择器:伪类和伪元素. 常用的一些伪类选择器: :link :visited ...
- 长沙理工大学第十二届ACM大赛L 选择困难症 (剪枝暴搜)
链接:https://ac.nowcoder.com/acm/contest/1/L 来源:牛客网 选择困难症 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 131072K,其他语言 ...
- 八、ARM 汇编程序格式和程序控制
8.1 汇编程序格式 源程序中的语句可以分为两种类型:指令性语句.指示性语句 指示性语句就是一些伪操作,在 MDK 编译环境下的伪操作有下面几种: 符号定义伪操作 数据定义伪操作 汇编控制伪操作 其他 ...