转自: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. Eclipse - FindBugs Plugin 的安装和使用

    Eclipse -  FindBugs Plugin 的安装和使用 FindBugs is a static analysis tool that examines the classes in se ...

  2. 解决eclipse maven 项目重新下载包这个问题

    问题:eclipse项目使用maven下载依赖包,但是有时候断网什么来着就不会自动下载了,挺蛋疼了. 所以,需要我们重新更新项目下载呢. 首先是要在maven的conf文件下setting.xml配置 ...

  3. Python中的split()函数的使用方法

    函数:split() Python中有split()和os.path.split()两个函数,具体作用如下:split():拆分字符串.通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(lis ...

  4. typeof和GetType的区别

    http://stackoverflow.com/questions/4537945/what-is-the-difference-of-getting-type-by-using-gettype-a ...

  5. Oracle数据泵导入导出数据,建立表空

    Oracle11g 数据导入到oracle10g 中:1.在oracle11g 服务器命令行中用expdp 导出数据expdp ts/ts@orcl directory=expdp_dir dumpf ...

  6. Asp.Net生成RSS方法

    一.RSS简介 什么是RSS? RSS是一种网页内容联合格式(web content sydication format). 它的名字是Really Simple Syndication的缩写. RS ...

  7. WebApp开发框架Ionic+AngularJS+Cordova

    目前的手机APP有三类:原生APP.WebAPP.HybridApp:HybridApp结合了前两类APP各自的优点,越来越流行. Ionic Ionic是一个新的.可以使用HTML5构建混合移动应用 ...

  8. Self-Paced Training (3) - Docker Operations

    AgendaTroubleshooting ContainersOverview of Security PracticesPrivate RegistryIntro to Docker Machin ...

  9. AssetManager asset的使用

    Android 系统为每个新设计的程序提供了/assets目录,这个目录保存的文件可以打包在程序里./res 和/assets的不同点是,android不为/assets下的文件生成ID.如果使用/a ...

  10. 物联网操作系统HelloX V1.78测试版正式发布

    经过HelloX开发团队近四个月的努力,在HelloX V1.77版本基础上,增加许多功能特性,并对V1.77版本的一些特性进行了进一步优化之后,正式形成HelloX V1.78测试版本,经相对充分的 ...