问题描述
老蛤有一堆真正的粉丝。
老蛤年迈了。不过好在他有特别多忠实粉丝,愿意献出自己寿命的1s等价交换为他的寿命+1s。
老蛤与粉丝们在一个面积为 的城市中。老蛤可以吸收距离不超过s的粉丝所提供的寿命。老蛤所在的十字路口(a,b)与粉丝所在的十字路口(c,d)之间距离是|a-c|+|b-d|。
老蛤的洪荒之力会不断变化q次,导致s的值也会变化多次。现在要求你,最聪明的粉丝,计算出对于这q个s,每次最多增加多少秒的寿命。
输入格式
第一行四个整数n,k,q代表城市面积为n*n,粉丝数目k,q次功力变化;
接下来k行,每行两个整数,为粉丝坐标 xi,yi;
接下来q行,每行一个整数,为当前最大距离s。
输出格式
对于每次询问,输出一行。每一行只包含一个整数,代表最多增加多少秒的寿命。
样例输入
样例输出
数据范围
题解
老蛤可以吸收的寿命就是老蛤可以吸收的范围内所有粉丝的数量。
枚举中心点,发现老蛤可以吸收的范围是一个菱形。
把直角坐标系旋转45°,菱形就变成了矩形。
维护二维前缀和,O(1)统计答案。
1 #include <cstdio> 2 const int maxn=1000; 3 int n,K,Q,p[10000005][2],sum[2005][2005],pt,s; 4 int min(int x,int y) 5 { 6 return x<y?x:y; 7 } 8 int max(int x,int y) 9 { 10 return x>y?x:y; 11 } 12 int main() 13 { 14 int i,j,x,y,x1,x2,y1,y2; 15 scanf("%d%d%d",&n,&K,&Q); 16 for (i=1;i<=K;i++) 17 scanf("%d%d",&x,&y), 18 sum[x+y][x-y+n]++; 19 for (i=1;i<=n;i++) 20 for (j=1;j<=n;j++) 21 p[++pt][0]=i+j, 22 p[pt][1]=i-j+n; 23 int n2=n*2; 24 for (i=1;i<=n2;i++) 25 for (j=1;j<=n2;j++) 26 sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; 27 int ans=0; 28 while (Q--) 29 { 30 scanf("%d",&s); 31 if (s>n+1) 32 { 33 printf("%d\n",K); 34 continue; 35 } 36 ans=0; 37 for (i=1;i<=pt;i++) 38 x1=max(p[i][0]-s-1,0),y1=max(p[i][1]-s-1,0), 39 x2=min(p[i][0]+s,n2),y2=min(p[i][1]+s,n2), 40 ans=max(ans,sum[x2][y2]-sum[x2][y1]-sum[x1][y2]+sum[x1][y1]); 41 printf("%d\n",ans); 42 } 43 return 0; 44 }