HDU 4312 Crowd

第一次用hash,第一次用二维树状数组,这道题所涉及到的知识点对我来说几乎是全新的。

于是乎这道题花去了我一晚上加一上午搞。

一开始直接开10001*10001的数组,维护N棵树状数组,结果显然爆内存了。不过现场赛的时候据说这样就能过,泥玛坑啊!~

后来搜题解,才知道。好吧,用过一维树状数组的童鞋学二维应该马上就能上手的,这里贴一个二维树状数组的资料。

二维树状数组资料:http://www.java3z.com/cwbwebhome/article/article1/1369.html?id=4804

 至于hash这里用到的都是简单映射,看完hash的百度词条就能做这题了。

其实这道题的关键是在于坐标转换,转换完了直接就是二维树状数组的裸题了。

这道题我主要参考了沐阳的题解,大家也可以去看一下,两个参照着看效果可能好一点:http://www.cnblogs.com/Lyush/archive/2013/06/05/3119486.html

下面讲一下作为一个刚刚接触到这些知识点的人对于这道题的理解。

首先,在图上明显可以看出,以(x,y)为中心,曼哈顿距离为z的点构成了一个菱形,求的是菱形内所有点之和。

所以我们要想一个办法,把他们转换为矩形,这样就可以用二维树状做了。

这里就要用到坐标转换了,显然把当前的菱形旋转45度就是一个矩形了. 。

所以,我们把当前的方格网络映射到另一个矩形(以下称做映射矩阵)里去,转换公式是:nx = x-y+n;  ny = x+y-1;

转换后的矩形大小是2N*2N,至于怎么推导公式,我暂时还不知到。大家可以去用这个公式将原图和映射图画出来,就能体会到这个公式的奇妙之处了。

   

原图是这样的,可以看到,标记的矩形有的行有三个点,有的行只有两个点,这使得二维树状数组无法使用。

然而转换公式有这样一个效果:

    设原图中(x0,y0)映射到映射矩阵中的(x,y),转换公式使得原图不存在 和映射矩阵中(x-1,y)、(x+1,y)、(x,y-1)、(x,y+1) 相对应的点。

这样的效果使我们在求每一行的和的时候,可以在映射矩阵中直接按照(max(1,x-z) , min(n,x+z))的方法来求。

因为就算这一行只有两个点,而我们算了三个点,但是这多出来的一个点是0值。在原图中是没有任何值与之对应的。

然后直接就是二维树状数组的裸题。

但是这里要注意,我们显然开不了2N*2N的数组,而可能发生变化的数只有M*logn*logn个,大概是512万,不过根本不可能用到这么大,沐阳的代码400w就过了,后来我发先事实上400w还是卡着内存开的,我用的5000011就超内存了,所以我就把他的大素数抄过去用了。而之所以我的代码没有沐阳的快,那是因为他用了两个内联函数,这两个函数可能会被调用数十万次,这样子速度差就出来了,不过无所谓啦~

所以我们需要把这些二维数组里的数映射到一个一维数组里,直接找一个大素数来做hash映射就可以了。

下面上代码:

  1 #include<stdio.h>
  2 #include<iostream>
  3 using namespace std;
  4 
  5 #include<math.h>
  6 #include<stdlib.h>
  7 #include<algorithm>
  8 #include<string>
  9 #include<string.h>
 10 #include<map>
 11 #include<queue>
 12 #define repA(p,q,i)  for(int (i)=(p); (i)!=(q); ++(i) )
 13 #define repD(p,q,i)  for(int (i)=(p); (i)!=(q); --(i) )
 14 #define repAE(p,q,i)  for(int (i)=(p); (i)<=(q); ++(i) )
 15 #define repDE(p,q,i)  for(int (i)=(p); (i)>=(q); --(i) )
 16 #define MOD 4073989
 17 
 18 int n,m;
 19 int p,x,y,z;
 20 int LIM;
 21 int set[MOD];  //  用来表示映射矩阵的值
 22 int to[MOD];  //  用来做hash映射,表示坐标(x,y)映射到一维数组中的位置 
 23           // 在hash函数中采用的处理方法,使得可以不用邻接表去储存,其中i表示映射到的位置;
 24 
 25 int lowbit( int i );
 26 void getxy(int x, int y, int &nx, int &ny);
 27 int hash(int x, int y);
 28 int search(int x, int y);
 29 void update(int x, int y, int z);
 30 long long sum(int x, int y);
 31 
 32 
 33 int main()
 34 {
 35     while( scanf("%d",&n) != EOF )
 36     {
 37         if(n==0) break;
 38         LIM = (n<<1) ;
 39         memset(to,0,sizeof(to) );
 40         memset(set,0,sizeof(set) );
 41         scanf("%d",&m);
 42         int nx,ny,x1,xn,y1,yn;
 43         while(m--)
 44         {
 45             scanf("%d%d%d%d",&p,&x,&y,&z);
 46             getxy(x,y,nx,ny);
 47             if(p == 1)
 48                 update(nx,ny,z);
 49             else if(p == 2)
 50             {
 51                 x1 = max(1, nx-z);
 52                 y1 = max(1, ny-z);
 53                 xn = min(LIM, nx+z);
 54                 yn = min(LIM, ny+z);
 55                 cout<<sum(xn,yn)-sum(xn,y1-1)-( sum(x1-1,yn)-sum(x1-1,y1-1) ) <<endl;
 56             }
 57         }
 58     }
 59     return 0;
 60 }
 61 
 62 int lowbit( int i )
 63 {
 64     return i & (-i) ;
 65 }
 66 
 67 void getxy(int x, int y, int &nx, int &ny)
 68 {
 69     nx = x-y+n;
 70     ny = x+y-1;
 71     return ;
 72 }
 73 
 74 int hash(int x, int y)
 75 {
 76     int loc = x*LIM + y;
 77     int key =  loc % MOD;
 78     for(int i=key; ; ++i)
 79     {
 80         if(i == MOD)  i=0;
 81         if(  to[i]  &&  to[i] != loc ) {}
 82         else 
 83         {
 84             to[i] = loc;
 85             return i;
 86         }
 87     }
 88 }
 89 
 90 int search(int x, int y)
 91 {
 92     int loc = x*LIM + y;
 93     int key =  loc % MOD;
 94     for(int i=key; ; ++i)
 95     {
 96         if(i == MOD)  i=0;
 97         if( to[i]  &&  to[i] != loc ) {}
 98         else 
 99         {
100             return i;
101         }
102     }
103 }
104 
105 void update(int x, int y, int z)
106 {
107     for(int i=x; i<=LIM; i+=lowbit(i) )
108       for(int j=y; j<=LIM; j+=lowbit(j) )
109       set[ hash(i,j) ] += z;
110     return ;
111 }
112 
113 long long sum(int x, int y)
114 {
115     long long all=0;
116     for(int i=x; i>0; i-=lowbit(i) )
117       for(int j=y; j>0; j-=lowbit(j) )
118       all += set[search(i,j) ];
119     return all;
120 }
View Code

 

posted on 2013-10-15 10:32  码农之上~  阅读(242)  评论(0编辑  收藏  举报

导航