Crowd
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2663 Accepted Submission(s): 640
Since frequent accidents had happened last year when the citizens went out to admire the colorful lanterns, City F is planning to develop a system to calculate the degree of congestion of the intersection of two streets.
The map of City F is organized in an N×N grid (N north-south streets and N west-east street). For each intersection of streets, we define a density value for the crowd on the intersection.
Initially, the density value of every intersection is zero. As time goes by, the density values may change frequently. A set of cameras with new graphical recognition technology can calculate the density value of the intersection easily in a short time.
But the administrator of the police office is planning to develop a system to calculate the degree of congestion. For some consideration, they come up with a conception called "k-dimension congestion degree". The "k-dimension congestion degree" of intersection (x0,y0) is represented as "c(x0,y0,k)", and it can be calculated by the formula below:
Here, d(x,y) stands for the density value on intersection (x,y) and (x,y) must be in the N×N grid. The formula means that all the intersections in the range of manhattan distance k from (x0,y0) effect the k-dimension congestion degree of (x0,y0) equally, so we just simply sum them up to get the k-dimension congestion degree of (x0,y0).
The figure below shows a 7×7 grid, and it shows that if you want to get the 2-dimension congestion degree of intersection (4,2),you should sum up the density values of all marked intersections.
Each test case begins with a line with two integers N, M, meaning that the city is an N×N grid and there will be M queries or events as time goes by. (1 ≤ N ≤10 000, 1 ≤ M ≤ 80 000) Then M lines follow. Each line indicates a query or an event which is given in form of (p, x, y, z), here p = 1 or 2, 1 ≤ x ≤ N, 1 ≤ y ≤ N.
The meaning of different p is shown below.
1. p = 1 the value of d(x,y) is increased by z, here -100 ≤ z ≤ 100.
2. p = 2 query the value of c(x,y,z), here 0 ≤ z ≤ 2N-1.
Input is terminated by N=0.
大意就是給定一個矩陣,有兩種操作,一種是更改某個點的值,一種是查詢該點曼哈頓距離內的點值。
曼哈頓距離表示的是一個菱形,所以每個點旋轉45°。
新點的座標表示爲整數的話就是:(x-y,x+y)
爲了防止x-y<0,將橫座標加n即可,所以處理點就是(x-y+n,x-y)
再加上這個題數據量大,用離散化處理一下,將二維的座標映射成爲一個數字,用樹狀數組維護更新和查詢即可。
代碼如下:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#define N 3001003
using namespace std;
int x[N],y[N];
int sym[N],val[N];
int num[N],tree[N];
int cnt;
int n,m;
int H;
int lowbit(int i)
{
return i&(-i);
}
void get(int x,int y)
{
for(int i=x;i<=H;i+=lowbit(i))
{
for(int j=y;j<=H;j+=lowbit(j))
{
num[cnt++]=i*(H+1)+j;
//這裏將二維的座標映射成爲一個數字,i乘的數字最小爲H,當小於H時加j有可能使得兩個座標投影爲同一個數字
}
}
}
void add(int x,int y,int val)
{
for(int i=x;i<=H;i+=lowbit(i))
{
for(int j=y;j<=H;j+=lowbit(j))
{
int pos=lower_bound(num,num+cnt,i*(H+1)+j)-num;
tree[pos]+=val;
}
}
}
int query(int x,int y)
{
int sum=0;
for(int i=x;i>0;i-=lowbit(i))
{
for(int j=y;j>0;j-=lowbit(j))
{
int pos=lower_bound(num,num+cnt,i*(H+1)+j)-num;
if(num[pos]==i*(H+1)+j)
sum+=tree[pos];
}
}
return sum;
}
int main()
{
int newx,newy;
while(scanf("%d",&n)!=EOF&&n)
{
scanf("%d",&m);
H=n*2;//座標擴大爲與來的2倍
cnt=0;
memset(tree,0,sizeof(tree));
memset(num,0,sizeof(num));
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&sym[i],&x[i],&y[i],&val[i]);
newx=x[i]-y[i]+n;
newy=x[i]+y[i];
if(sym[i]==1)
get(newx,newy);
}
//printf("%d\n",cnt);
sort(num,num+cnt);
cnt=unique(num,num+cnt)-num;
//unique將重複的元素去掉,加在數組的最後
for(int i=0;i<m;i++)
{
newx=x[i]-y[i]+n;
newy=x[i]+y[i];
if(sym[i]==1)
add(newx,newy,val[i]);
else
{
int x1=max(1,newx-val[i]);//防止越界
int x2=min(H,newx+val[i]);
int y1=max(1,newy-val[i]);
int y2=min(H,newy+val[i]);
printf("%d\n",query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1));
}
}
}
return 0;
}