转自:http://blog.csdn.net/sdj222555/article/details/10828607

大意就是给出一个矩阵

初始每个位置上的值都为0

然后有两种操作

一种是更改某个位置上的值

另一个是求某个位置附近曼哈顿距离不大于K的所有位置的值的总和

然后这里用了一个非常牛叉的技巧

将所有点绕原点左旋45°

然后新的坐标也很好计算

x' = (x - y) * sqrt(2) / 2

y' = (x + y) * sqrt(2) / 2

由于都是小数

所以乘个sqrt(2) 就成整数了

x' = (x - y)

y' = x + y

由于x- y可能是负数。所以把点都右移一下  x' = x + y + n (n是矩阵宽度)然后矩阵的宽度和长度也就各自扩大了一倍

然后我们就可以惊奇的发现

原先是求 abs(x - x0) + abs(y - y0) <= k 的所有位置的值的和

现在变成了 abs(x' - x0') <= k 或者abs(y' - y0') <= k 就可以了

也就变成了求一个子矩阵的和

然后就可以欢快的用二维树状数组来解了

但是发现题目给的范围比较大

1W*1W的矩阵

但是询问的话 有8W

那么我们可以就把所有询问中树状数组操作过程中用到的点给离散出来。

然后就可以节省内存了

离散的话可以有两种方法

一种是线性探测再散列

这个可以在线处理询问

另一个就是先把所有可能用到的都取出来,然后先都离散了,离线处理询问

离散之后,每个x,y都应该对应一个唯一的数。我们就可以用一个一维的数组,来完成这个二维树状数组的功能

首先是先把询问存起来的离散方式

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio> using namespace std; const int N = ;
const int M = ; int W; // 坐标转换后的边长
int h[M*], cnt;
int bit[M*];
int op[M], x[M], y[M], v[M]; int lowbit(int x) {
return x&-x;
}
void ready(int x, int y) {
for (int i = x; i <= W; i += lowbit(i)) {
for (int j = y; j <= W; j += lowbit(j)) {
h[cnt++] = i*W+j;
}
}
}
void add(int x, int y, int val) {
for (int i = x; i <= W; i += lowbit(i)) {
for (int j = y; j <= W; j += lowbit(j)) {
int pos = lower_bound(h, h+cnt, i*W+j) - h;
bit[pos] += val;
}
}
}
int getsum(int x, int y) {
int sum = ;
for (int i = x; i > ; i -= lowbit(i)) {
for (int j = y; j > ; j -= lowbit(j)) {
int pos = lower_bound(h, h+cnt, i*W+j) - h;
if (h[pos] == i*W+j) sum += bit[pos]; // 没处理过的数是0 不用考虑
}
}
return sum;
} int main()
{
int n, m;
while (~scanf("%d", &n) && n) {
scanf("%d", &m);
W = n*;
cnt = ;
memset(bit, , sizeof bit);
int tx, ty;
for (int i = ; i < m; ++i) {
scanf("%d%d%d%d", &op[i], &tx, &ty, &v[i]);
x[i] = tx - ty + n;
y[i] = tx + ty;
if (op[i] == ) { // 1 means update, 2 means query
ready(x[i], y[i]);
}
}
sort(h, h+cnt);
cnt = unique(h, h+cnt) - h;
for (int i = ; i < m; ++i) {
if (op[i] == ) {
add(x[i], y[i], v[i]);
} else {
int L = max(, x[i]-v[i]);
int B = max(, y[i]-v[i]);
int R = min(W, x[i]+v[i]);
int T = min(W, y[i]+v[i]);
printf("%d\n", getsum(R,T) - getsum(L-,T)-getsum(R,B-)+getsum(L-,B-));
}
}
}
return ;
}

HDU4456-Crowd(坐标旋转+二位树状数组+离散化)的更多相关文章

  1. 【poj2155】【Matrix】二位树状数组

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=34310873 Description Given ...

  2. POJ-2155-Matrix二位树状数组应用

    题目: 一个只有0和1构成的二维平面,给你两种指令,一种是区间的更新,即0变为1,1变为0:一种是查询一个点是1还是0: 由于是二进制,所以每次更新在相应的点上加一,最后对2取余即可. 至于二维的树状 ...

  3. hdu4456 Crowd(二维树状数组)

    题意:给出一个n*n的矩阵,然后m个operation,1表示坐标(x,y)的值加z,2表示与坐标(x,y)的曼哈顿距离不超过z的点的权值和. 解题思路:将矩阵側过来45度.发现询问的时候,有效的点构 ...

  4. 【 HDU - 4456 】Crowd (二维树状数组、cdq分治)

    BUPT2017 wintertraining(15) #5A HDU 4456 题意 给你一个n行n列的格子,一开始每个格子值都是0.有M个操作,p=1为第一种操作,给格子(x,y)增加z.p=2为 ...

  5. poj 1195:Mobile phones(二维树状数组,矩阵求和)

    Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14489   Accepted: 6735 De ...

  6. [POJ2155]Matrix(二维树状数组)

    题目:http://poj.org/problem?id=2155 中文题意: 给你一个初始全部为0的n*n矩阵,有如下操作 1.C x1 y1 x2 y2 把矩形(x1,y1,x2,y2)上的数全部 ...

  7. MooFest_二维树状数组

    Description Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a s ...

  8. 二维树状数组(水题) POJ1195

    前段时间遇到线段树过不了,树状数组却过了的题.(其实线段树过得了的) 回忆了下树状数组. 主要原理,还是二进制位数,每一项的和表示其为它的前((最后一位1及其后)的二进制数)和,可从二进制图来看.(用 ...

  9. 二维树状数组——SuperBrother打鼹鼠(Vijos1512)

    树状数组(BIT)是一个查询和修改复杂度都为log(n)的数据结构,主要用于查询任意两位之间的所有元素之和,其编程简单,很容易被实现.而且可以很容易地扩展到二维.让我们来看一道很裸的二维树状数组题: ...

随机推荐

  1. 选择语句----switch case

    今天学习了选择语句的 switch case是多选一的情况可以使用. 案例: //分别输入月份 几号 输出是今年的多少天 //每年的1,3,5,7,8,10,12月是31天 //今年的2月是28天 其 ...

  2. web前端性能测试小点

    关于前端性能的文章: http://www.cnblogs.com/fnng/archive/2011/09/19/2181894.html web应用的前端性能响应时间指浏览器的页面加载时间.浏览器 ...

  3. Generic Data Access Layer泛型的数据访问层

    http://www.codeproject.com/Articles/630277/Generic-Data-Access-Layer-GDA-Part-I http://www.codeproje ...

  4. Android测试框架-uiautomator

    官方示例:https://github.com/googlesamples/android-testing 官方文档请 google 要求: Android SDK v23 Android Build ...

  5. devDependencies和dependencies的区别

    我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如: --save-dev --save 在 package.json 文件里面 ...

  6. 修改数据库中group_concat的返回结果的长度限制

    修改数据库中group_concat的返回结果的长度限制 我们可以使用Mysql的客户端管理工具,Sqlyog 新建一个查询编辑器 显示  SHOW VARIABLES LIKE "grou ...

  7. UVALive 3661 Animal Run(最短路解最小割)

    题意:动物要逃跑,工作人员要截断从START(左上角)到END(右下角)的道路,每条边权表示拦截该条道路需要多少工作人员.问最少需要多少人才能完成拦截. 通俗地讲,就是把图一分为二所造成消耗的最小值. ...

  8. uva 10047 The Monocycle(搜索)

    好复杂的样子..其实就是纸老虎,多了方向.颜色两个状态罢了,依旧是bfs. 更新的时候注意处理好就行了,vis[][][][]要勇敢地开. 不过这个代码交了十几遍的submission error,手 ...

  9. LeetCode Letter Combinations of a Phone Number 电话号码组合

    题意:给一个电话号码,要求返回所有在手机上按键的组合,组合必须由键盘上号码的下方的字母组成. 思路:尼玛,一直RE,题意都不说0和1怎么办.DP解决. class Solution { public: ...

  10. LeetCode: MergekSortedLists

    Title: Merge k sorted linked lists and return it as one sorted list. Analyze and describe its comple ...