题意:

给出一个矩阵,初始每个位置上的值都为0,然后有两种操作

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

技巧:

  • 坐标旋转,使得操作之后菱形变成方方正正的矩形,(即“曼哈顿距离”转化为“切比雪夫距离”)方便使用树状数组进行计算。
  • 利用哈希进行离散,节约空间,即不开不必要的空间。

坐标旋转:

  • X=x-y
  • Y=x+y

这个结果显示,A’B’C’D’(X,Y)是ABCD(x,y)绕原点(0,0)左旋转45°后的结果,同时长度变为原来的sqrt(2)倍。

由于菱形范围为对角线OA的距离,正方形为一半边长OM的距离,相等,所以无需对距离进行操作。

缩小范围:

小于0和大于2*n的一定无值。

坐标离散:

1,离线离散

之前学主席树的时候经常这样搞。http://www.cnblogs.com/hua-dong/p/7931778.html

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
const int maxm=;
int q[maxm],a[maxm],b[maxm],c[maxm];
int hs[maxn],sz,Lim,n;
int Val[maxn];
int max(int x,int y){ if(x>y) return x;return y;}
int min(int x,int y){ if(x<y) return x;return y;}
int lowbit(int x) { return x&(-x); }
void addhs(int x,int y)
{
for(int i=x;i<=Lim;i+=lowbit(i))
for(int j=y;j<=Lim;j+=lowbit(j)) {
hs[++sz]=i*Lim+j ;
}
}
void add(int x,int y,int val)
{
for(int i=x;i<=Lim;i+=lowbit(i))
for(int j=y;j<=Lim;j+=lowbit(j)){
int pos=lower_bound(hs+,hs+sz+,i*Lim+j)-hs;
Val[pos]+=val;
}
}
int getsum(int x,int y)
{
int res=;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j)){
int pos=lower_bound(hs+,hs+sz+,i*Lim+j)-hs;
if(hs[pos]==i*Lim+j) res+=Val[pos];
}
return res;
}
int main()
{
int i,m;
while(~scanf("%d",&n)){
if(n==) return ;
sz=;Lim=n<<;
memset(Val,,sizeof(Val));
scanf("%d",&m);
for(i=;i<=m;i++){
scanf("%d%d%d%d",&q[i],&a[i],&b[i],&c[i]);
if(q[i]==) addhs(a[i]-b[i]+n,a[i]+b[i]);
}
sort(hs+,hs+sz+);
sz=unique(hs+,hs+sz+)-(hs+);
for(i=;i<=m;i++)
{
if(q[i]==){
add(a[i]-b[i]+n,a[i]+b[i],c[i]);
}
else {
int X1=max(,a[i]-b[i]+n-c[i]);
int Y1=max(,a[i]+b[i]-c[i]);
int X2=min(Lim,a[i]-b[i]+n+c[i]);
int Y2=min(Lim,a[i]+b[i]+c[i]);
printf("%d\n",getsum(X2,Y2)-getsum(X1-,Y2)+getsum(X1-,Y1-)-getsum(X2,Y1-));
}
}
}
return ;
}

2,线性探测再散列。

以前再kbrdhash时用到过,大同小异吧http://www.cnblogs.com/hua-dong/p/7714475.html

但是这种解法能否AC,完全看Mod是否取到合适的值。(我换了好多个才AC了,心累)。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
const int Mod=;
int Laxt[Mod],Next[Mod],H[Mod],cnt;
int q,a,b,c;
int Val[Mod],Lim,n;
int max(int x,int y){ if(x>y) return x;return y;}
int min(int x,int y){ if(x<y) return x;return y;}
int lowbit(int x) { return x&(-x); }
int find(int x,int opt)
{
int tmp=x%Mod;
for(int i=Laxt[tmp];i;i=Next[i]){
if(H[i]==x) return i;
}
if(opt==) return x=;
Next[++cnt]=Laxt[tmp];
Laxt[tmp]=cnt;
H[cnt]=x;
return cnt;
}
void add(int x,int y,int val)
{
for(int i=x;i<=Lim;i+=lowbit(i))
for(int j=y;j<=Lim;j+=lowbit(j)){
int pos=find(i*Lim+j,);
Val[pos]+=val;
}
}
int getsum(int x,int y)
{
int res=;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j)){
int pos=find(i*Lim+j,);
if(H[pos]==i*Lim+j) res+=Val[pos];
}
return res;
}
int main()
{
int i,m;
while(~scanf("%d",&n)){
if(n==) return ;
cnt=;Lim=n<<;
memset(Val,,sizeof(Val));
memset(Laxt,,sizeof(Laxt));
scanf("%d",&m);
for(i=;i<=m;i++)
{
scanf("%d%d%d%d",&q,&a,&b,&c);
if(q==) add(a-b+n,a+b,c);
else {
int X1=max(,a-b+n-c);
int Y1=max(,a+b-c);
int X2=min(Lim,a-b+n+c);
int Y2=min(Lim,a+b+c);
printf("%d\n",getsum(X2,Y2)-getsum(X1-,Y2)+getsum(X1-,Y1-)-getsum(X2,Y1-));
}
}
}
return ;
}

经验:

为什么不把查询用到的点也离散呢?后面getsum的那些点不是到用到吗-----就算用到他们的值也为0。

算是加深对数状数组的存储位置一个更好的理解吧。

(类似用到了坐标转化的题:HDU4312)

HDU4456-Crowd (坐标旋转处理+hash处理+二维树状数组)的更多相关文章

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

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

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

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

  3. 牛客网 暑期ACM多校训练营(第二场)J.farm-STL(vector)+二维树状数组区间更新、单点查询 or 大暴力?

    开心.jpg J.farm 先解释一下题意,题意就是一个n*m的矩形区域,每个点代表一个植物,然后不同的植物对应不同的适合的肥料k,如果植物被撒上不适合的肥料就会死掉.然后题目将每个点适合的肥料种类( ...

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

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

  5. MooFest_二维树状数组

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

  6. hdu 2642 二维树状数组 单点更新区间查询 模板水题

    Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Subm ...

  7. (简单) POJ 1195 Mobile phones,二维树状数组。

    Description Suppose that the fourth generation mobile phone base stations in the Tampere area operat ...

  8. Stars(二维树状数组)

    Stars Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others) Total Submiss ...

  9. POJ 2155 Matrix 【二维树状数组】(二维单点查询经典题)

    <题目链接> 题目大意: 给出一个初始值全为0的矩阵,对其进行两个操作. 1.给出一个子矩阵的左上角和右上角坐标,这两个坐标所代表的矩阵内0变成1,1变成0. 2.查询某个坐标的点的值. ...

随机推荐

  1. java位运算定义常量

    简单说一下位运算 按位与(&) 参加运算的两个数,换算为二进制(0.1)后,进行与运算.只有当相应位上的数都是1时,该位才取1,否则该为为0 按位或(|) 参加运算的两个数,换算为二进制(0. ...

  2. PJzhang:一道看线索找答案的逻辑题

    猫宁!!! 这道逻辑题,2年前就有打算解决,但是没上心,今天抽空梳理出来了思路,逻辑上可以跑的通,不至于以后慢慢忘了,这道题和数独题基本类似,但是也许更花时间,做这种题最好看着线索列图标,省的不停翻页 ...

  3. R数据分析(一)

    R语言特点: 主要用于统计分析.图表显示.   属于解释型语言.支持模块化编程. 应用:数据科学.统计计算.机器学习   学习方法: 做笔记,记重点或者心得 手动实践,加深理解 坚持练习,利用身边数据 ...

  4. Nginx安装出现‘struct crypt_data’没有名为‘current_sal

    centos 安装nginx 时出现src/os/unix/ngx_user.c:26:7: 错误:‘struct crypt_data’没有名为‘current_sal 解决办法: 将系统换成版本低 ...

  5. 【Spring 源码】ApplicationContext源码

    ApplicationConetxt体系

  6. sql server第三方产品

    sql server第三方产商工具 双活: 1. Moebius for SQL Server :http://www.grqsh.com/Subpage/product_MoebiusDA.html ...

  7. 【0.1】mysql版本升级(5.6升级到5.7)

    目录 [1].升级操作 [2].mysql 5.6安装(二进制) [3].mysql 5.7安装(二进制) [1].升级操作 核心步骤 [1.1]停止mysql 5.6 [1.2]把环境变量引用到My ...

  8. redis缓存雪崩

    缓存雪崩 缓存雪崩,是指在某一个时间段,缓存集中过期失效. 产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时.那么 ...

  9. Python基础字符串前加u,r,b,f含义

    1.字符串前加 u 例:u"我是含有中文字符组成的字符串." 作用: 后面字符串以 Unicode 格式 进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时 ...

  10. Spring 中的bean 是线程安全的吗?

    结论: 不是线程安全的 Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体sco ...