转自: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. Java API —— BigInteger类

    1.BigInteger类概述        可以让超过Integer范围内的数据进行运算 2.构造方法     public BigInteger(String val) 3.BigInteger类 ...

  2. 转:linux下面/usr/local和opt目录有何区别

    /usr/local下一般是你安装软件的目录,这个目录就相当于在windows下的programefiles这个目录 /opt这个目录是一些大型软件的安装目录,或者是一些服务程序的安装目录 /opt ...

  3. GridLayoutManager

    GridLayoutManager Class Overview A RecyclerView.LayoutManager implementations that lays out items in ...

  4. Android开发之源码:多次点击事件的原理和实现

    多次点击事件 多次点击事件原理:最后一次点击事件与第一次点击事件的时间间隔是否小于某个时间,当小于的时候,就认为这是一个多次点击事件. Android源码实现效果: import android.ap ...

  5. C#调用java程序

    前言: 最近跟项目组的人合作一个项目,由于之前我用的是java写的一个与android通信的程序,现在另一个同事来编写界面程序,由于C#编写起来比较方便,而我又不想重新写之前java的那段代码,于是需 ...

  6. public,protected,friendly,private的访问权限

    请说出作用域public,private,protected,以及不写时的区别 这四个作用域的可见范围如下表所示. 说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly. 作用域   ...

  7. UVa 120 Stacks of Flapjacks【构造法】

    题意:给出n张煎饼,从上到下输入,每张煎饼上面都有一个数字,厨师每次可以选择第k张煎饼,进行翻转操作,设计一种方法使得所有煎饼按照从小到大排序(最上面的煎饼最小) 首先是这个翻转的操作,如下图 如图所 ...

  8. FileZilla无法确定拖放操作的目标,由于shell未正确安装

    天有不测风云,突然间,用filezilla下载ftp上的文件到桌面的时候,提示"无法确定拖放操作目标.由于shell未正确安装" 解决办法很简单,执行如下几步就OK了 1.在CMD ...

  9. asp.net 使用JQuery 调用Ashx 后面直接写方法名,通过反射找到对应的方法

    using System.Reflection; public class Industry_Manager : IHttpHandler { HttpRequest gRequest = null; ...

  10. django访问静态文件

    DJANGO 1.6 静态文件处理 添加 STATICFILES_DIRS = (os.path.abspath('static'),) 新建static目录