Input file: standard inputOutput file: standard output Time limit: 1 secondMemory limit: 512 mebibytes
Last year, there were three soul artist in the team Abysswatcher. They were all addicted to painting, even when they were on the train. One day, they want to paint a paper. Iniii-th step, they choose a core grid (xi,yi)(x_i, y_i)(xi,yi) and paint all the grid near it (the Manhattan distance distance between the core and other grids are no more thanrir_iri). After some operates, they want to know the maximum times they painted the same grid.
Input
Three integers n,m,tn, m, tn,m,t(1≤n,m≤2000,1≤t≤2×1051 \le n, m \le 2000, 1 \le t \le 2 \times 10^51≤n,m≤2000,1≤t≤2×105)in one line. nnn and mmm represent the length and the width of the paper. ttt represents the times they painted.
In the following ttt lines, the iii-th contains three non-negative integers xi,yi,rix_i, y_i, r_ixi,yi,ri (1≤xi−ri,xi+ri≤n1 \le x_i - r_i, x_i + r_i \le n1≤xi−ri,xi+ri≤n,1≤yi−ri,yi+ri≤m1 \le y_i - r_i, y_i + r_i \le m1≤yi−ri,yi+ri≤m).
Output
Two integers in one line, represent the maximum times they painted the same grid and the number of such grid.
Examples
Input 1
6 6 4
2 2 1
2 3 1
3 2 0
3 4 2
Output 1
3 2
Note
The sample looks like this. The "Manhattan distance" of two points A,BA, BA,B equals to ∣Ax−Bx∣+∣Ay−By∣|A_x - B_x| + |A_y - B_y|∣Ax−Bx∣+∣Ay−By∣.
\ 1 2 3 4 5 6 -> x
1 1 1 1
2 1 2 3 2 1
3 3 2 1 1 1
4 1 1 1
5 1
6
|
v
y
这题的话如果暴力修改O(N^4)果断超时,当时读题的时候就有深深的预感,可以用矩阵前缀和(或者说BIT,但是没必要啊……),但是他是曼哈顿距离,是斜的。这个也好解决,大概用一个横纵坐标的变换就行了。当时就是这么想的,至于具体变换的方法,打算先放放,去调其他的题了,然后就放到了最后……再次追悔莫及,这个变换其实也是显而易见的。
首先简单的说说矩阵前缀和,对于普通一维区间前缀和,我们在区间左端点+1,右端点-1,然后求某一个具体值的时候就求和即可。至于矩阵前缀和,假设我们要修改左上点(x1,y1)和右下点(x2,y2)对应的矩阵区间,我们对[x1,y1]加1,[x1,y2+1]减1,[x1+1,y2]减1,[x2+1,y2+1]加1,然后求前缀和即可,这里的二维数组前缀和是指以[x,y]为右下角,起始点为左上角的矩阵中数字之和。好像和KD的同学讲过,然后这题也是类似。
至于对映的方式,一个点分别在两个对角线上,我们新的左边的x'和y'分别就表示两个所在的两个对角线的编号。我们发现,一个区域刚好是一个菱形(正方形),如果转一下恰好是矩形。用了映射过来的新坐标,会发现也恰好是一个矩形。然后用矩阵前缀和即可了。具体对应的话是(x,y)对应(x-y+m,x+y-1)。代码如下,其实好短的,好后悔当时不去写啊:
#include<bits/stdc++.h>
using namespace std;
int c[5000][5000];
int n,m,q,ans=0,t=0;
int main()
{
scanf("%d%d%d",&n,&m,&q);
memset(c,sizeof(c),0);
for(int i=1;i<=q;i++)
{
int x,y,r,x1,y1,x2,y2;
scanf("%d%d%d",&x,&y,&r);
x1=x-r-y+m,y1=x-r+y-1;
x2=x+r-y+m,y2=x+r+y-1;
c[x2][y2]++;
c[x2][y1-1]--;
c[x1-1][y2]--;
c[x1-1][y1-1]++;
}
for(int i=1;i<=m+n;i++)
for(int j=1;j<=n+m;j++)
c[i][j]+=c[i-1][j]+c[i][j-1]-c[i-1][j-1];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int x=i-j+m;
int y=i+j-1;
if (c[x][y]>ans) ans=c[x][y],t=1;
else if (c[x][y]==ans) t++;
}
printf("%d %d\n",ans,t);
return 0;
}