HDU4456-Crowd(坐标旋转+二位树状数组+离散化)

时间:2022-03-02 01:24:44

转自: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&lpar;二维树状数组&rpar;

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

  4. 【 HDU - 4456 】Crowd &lpar;二维树状数组、cdq分治&rpar;

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

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

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

  6. &lbrack;POJ2155&rsqb;Matrix(二维树状数组)

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

  7. MooFest&lowbar;二维树状数组

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

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

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

  9. 二维树状数组——SuperBrother打鼹鼠&lpar;Vijos1512&rpar;

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

随机推荐

  1. org&period;eclipse&period;wst&period;common&period;project&period;facet&period;core&period;xml文件模板,解决eclipse编译报错。

    <?xml version="1.0" encoding="UTF-8"?> <faceted-project> <fixed f ...

  2. ARCGIS获取图层下的要素信息及要素类转换为要素

    /// <summary> /// 得到需要的字段名和字段值 /// </summary> /// <param name="layer">&l ...

  3. 学习笔记——适配器模式Adapter

    适配器模式适用于将不一致的接口转换为一致的接口. 比如,去香港玩儿,带上了自己的笔记本电脑,结果晚上插电时就抓瞎了,电源插孔与插座不一致.WTF…… 插座是酒店装好的,不可能拆了换一个,电源是自己的, ...

  4. Java案例-用户注册邮箱绑定激活功能实现

    <–start–> 需求描述:当客户打开收到邮箱激活码的邮件,点击激活链接,正确填写激活码后就会完成邮箱激活的步骤. 在后台编程代码编写中,有以下几个要点: ① 接收客户的手机号码和邮箱激 ...

  5. Northwind数据库练习及参考答案

    --查询订购日期在1996年7月1日至1996年7月15日之间的订单的订购日期.订单ID.客户ID和雇员ID等字段的值 Create View Orderquery as Select OrderDa ...

  6. C&num;编程(二十)----------静态类

    如果类只包含静态的方法和属性,该类就是静态的.静态类在功能上与使用私有静态构造函数创建的类相同.不能创建静态类的实例.使用关键字static关键字,编译器可以检查用户是否不经意间给类添加了实例成员.如 ...

  7. 表示层设计模式&colon;Intercepting Filter(截取筛选器)模式

     上下文  问题  影响因素  解决方案  变体  示例  结果上下文  相关模式  致谢  上下文 对于任何一个曾经从头建立 Web 应用程序的人来说,他们都会有这样的体会:这项任务所需要的独立完成 ...

  8. 洛谷 P4593 【&lbrack;TJOI2018&rsqb;教科书般的*】

    题目分析 一眼看上去就像是一个模拟题目,但是\(n\)的范围过大. 冷静分析一下发现难点在于如何快速求出幂和. 考虑使用伯努利数. \(B_0=1\) \(B_n=-\frac{1}{n+1}\sum ...

  9. ES6初识- Class

    { //基本定义和生成实例 class Parent{ //构造函数 constructor(name='lisi'){ this.name=name; } //属性get,set get longN ...

  10. 2019湘潭校赛 H(dp)

    题目传送 dp是常规的:\(m^2\)的预处理:把位置存进vector然后\(O(1)\)算出想要的:WA点:要注意特意设置一下val[i][v.size()]=0,即全天都放鸽子则花费时间为0. # ...