HLJU 1188 Matrix (二维树状数组)
Matrix
Time Limit: 4 Sec Memory Limit: 128 MB
Description
给定一个1000*1000的二维矩阵,初始矩阵中每一个数都为1,然后为矩阵有4种操作.
S x1 y1 x2 y2:计算(x1,y1)、(x2,y2)围成的矩阵内全部元素的和。
A x y v:将(x,y)添加v
D x y v:将(x,y)降低v
M x1 y1 x2 y2 v:将(x1,y1)元素中的v转移到(x2,y2)中去。
全部操作数都为正数。
若某一操作将矩阵中元素降到1下面,一律按1处理。
x,y从0開始编号。
Input
第一行一个数t,代表例子个数:
每组例子第一行一个数m,代表m次操作,m<100000
接下来m行代表m次操作
Output
每组例子输出一个
Case i:
i代表第i个例子
对于每个操作S,输出一行,代表计算结果。
全部结果均不会超过int范围
Sample Input
1
4
A 1 1 1
M 1 1 2 2 1
D 2 2 1
S 1 1 2 2
Sample Output
Case 1:
4
解题思路:非常明显的就是一个非常典型的二维树状数组问题,树状数组部分全然就是模板,仅仅是要在详细解决实际问题的时候,有点技巧。最開始见到这题的时候,我马上想到了曾经切的楼教主出的Matrix,感觉非常相似。然后就直接搞了,后来发现開始,要初始化树状数组的c数组,由于矩阵的初值均为1。就用了两层循环。一个一个调用update()。结果居然超时了。
。
。然后又在其它地方优化了,还是超时。。。
就想了个办法。直接把c数组所有初始化为0。这样就不用一次次的去调用update()了(由于c要存的是他前面的和,如今全为0,和当然也为0了),然后在求区域和的时候。直接加上那个区间里的节点数(由于本来的矩阵中应该所有初始化为1的,可是我開始全初始化为0了。就把每一个节点都少了1,节点数也就是区间的面积)就可以。
还有就是要求保证原矩阵元素在操作之后不能小于1。详细能够先算出当前位置的元素值,
在操作之前把操作的数e改动。然后直接运行操作就可以。这里还学到了一个求当前位置元素的方法,直接用区域求和函数,对当前点求和。即map[a][b] = getsum( a, b, a, b ). 详见代码
楼教主的Matrix 见:http://blog.csdn.net/u013446688/article/details/38194977
AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 1002; #define lowbit(x) x & (-x) //lowbit函数 int c[maxn][maxn]; //树状数组的c数组 inline int update(int x, int y, int d){ //update函数
int i, j;
for(i=x; i<=1000; i+=lowbit(i))
for(j=y; j<=1000; j+=lowbit(j))
c[i][j] += d;
} inline int sum(int x, int y){ //sum函数
int ans = 0;
int i, j;
for(i=x; i>0; i-=lowbit(i))
for(j=y; j>0; j-=lowbit(j))
ans += c[i][j];
return ans;
} int getsum(int x1, int y1, int x2, int y2){ //区域求和
return sum(x2, y2) - sum(x1-1, y2) - sum(x2, y1-1) + sum(x1-1, y1-1);
} int main(){
// freopen("in.txt","r",stdin);
int T, m ,a, b, cc, d, e;
string p;
scanf("%d", &T);
for(int t=1; t<=T; t++){
scanf("%d", &m);
printf("Case %d:\n", t);
memset(c, 0, sizeof(c));
while(m--){
cin>>p;
if(p[0] == 'A'){
scanf("%d%d%d", &a, &b, &e);
a++; b++;
update(a, b, e);
}
else if(p[0] == 'D'){
scanf("%d%d%d", &a, &b, &e);
a++; b++;
int k = getsum(a, b, a, b); //求当前位置的元素的值
if(k - e < 0) e = k; //改动e, 保证操作之后元素不小于1
update(a, b, -e);
}
else if(p[0] == 'M'){
scanf("%d%d%d%d%d", &a, &b, &cc, &d, &e);
a++; b++; cc++; d++;
int k = getsum(a, b, a, b); //同上
if(k - e < 0) e = k;
update(a, b, -e); update(cc, d, e);
}
else{
scanf("%d%d%d%d", &a, &b, &cc, &d);
a++; b++; cc++; d++;
if(cc < a) swap(a, cc);
if(d < b) swap(b, d);
int ans = getsum(a, b, cc, d) + (cc-a+1)*(d-b+1); //求矩阵区域和
printf("%d\n",ans);
}
}
}
return 0;
}
HLJU 1188 Matrix (二维树状数组)的更多相关文章
- [poj2155]Matrix(二维树状数组)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 25004 Accepted: 9261 Descripti ...
- 【poj2155】Matrix(二维树状数组区间更新+单点查询)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- POJ 2155 Matrix(二维树状数组,绝对具体)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 20599 Accepted: 7673 Descripti ...
- POJ 2155:Matrix 二维树状数组
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 21757 Accepted: 8141 Descripti ...
- poj 2155 Matrix (二维树状数组)
题意:给你一个矩阵开始全是0,然后给你两种指令,第一种:C x1,y1,x2,y2 就是将左上角为x1,y1,右下角为x2,y2,的这个矩阵内的数字全部翻转,0变1,1变0 第二种:Q x1 y1,输 ...
- poj----2155 Matrix(二维树状数组第二类)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 16950 Accepted: 6369 Descripti ...
- Matrix 二维树状数组的第二类应用
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 17976 Accepted: 6737 Descripti ...
- POJ2155:Matrix(二维树状数组,经典)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- Matrix (二维树状数组)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- poj 2155 B - Matrix 二维树状数组
#include<iostream> #include<string> #include<string.h> #include<cstdio> usin ...
随机推荐
- 专题三:自定义Web服务器
前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网络中的协议有了大致的了解的, 本专题将针对HTTP协议定义一个Web服务器,我们平常浏览网页通过在浏览器中输入一个网址就可以看到 ...
- 6.12---bug
- Java多线程——线程之间的协作
Java多线程——线程之间的协作 摘要:本文主要学习多线程之间是如何协作的,以及如何使用wait()方法与notify()/notifyAll()方法. 部分内容来自以下博客: https://www ...
- leetcode375 Guess Number Higher or Lower II
思路: dp. https://leetcode.com/problems/guess-number-higher-or-lower-ii/discuss/ 实现: class Solution { ...
- 如何把mysql的列修改成行显示数据简单实现
如何把mysql的列修改成行显示数据简单实现 创建测试表: 1: DROP TABLE IF EXISTS `test`; 2: CREATE TABLE `test` ( 3: `year` int ...
- 梦想CAD控件关于比较问题
全图比较 怎么比较两个CAD图纸文件修改前后的不同部分呢?在工程图纸设计中,我们更多情况下可能需要对同一张工程图的前后修改部分进行对比,以确定工程图纸的改动部分及追溯原因,本教程演示了几种常见的比较方 ...
- HDU6189 Law of Commutation (数论)
题意:输入n和a 定义m等于2的n次方 求1-m有多少数使得 a^b = b^a (mod m) 题解:先打表找规律 发现a为奇数的答案只有b = a这一种 (不知道为什么也不想知道为什么 当a为偶数 ...
- C++ std::map的安全遍历并删除元素的方法
首先我们讲遍历std::map, 大部分人都能写出第一种遍历的方法,但这种遍历删除的方式并不太安全. 第一种 for循环变量: #include<map> #include<stri ...
- 13jsp、javaWeb开发模式
13jsp.javaWeb开发模式-2018/07/25 1.jsp jsp实际上就是servlet.jsp=html+java,为用户提供动态内容 不适合编写Java逻辑 2.JSP原理 翻译(生成 ...
- Java中对象流使用的一个注意事项
再写jsp的实验作业的时候,需要用到java中对象流,但是碰到了之前没有遇到过的情况,改bug改到崩溃!!记录下来供大家分享 如果要用对象流去读取一个文件,一定要先判断这个文件的内容是否为空,如果为空 ...