拿到这个问题我们要怎么去想呢,如果是暴力的修改的话,我们的复杂度为 m * 2r*r 的复杂度,这也太暴力了,我们要怎么办呢,我们能不能用差分数组来实现呢?
我们首先要看如何实现公式的转换
很显然我们可以利用公式实现转换,这也给我们做题提供了新的思路
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
const int N = (int)3e3+5;
int c[N][N];
int n,m;
int main(){
cin >> n >> m;
int x,y,r;
for(int k=1;k<=m;k++){
cin >> x >> y >> r;
for(int i=max(1,x-r);i<=min(n,x+r);i++){
// 一定要处理好边界
int t = r - abs(x-i);
c[i][max(1,y-t)]++;
c[i][min(n+1,y+t+1)]++; // 这个边界一定要注意,要超出n
}
}
int ans = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
c[i][j] += c[i][j-1];
if(c[i][j]&1) ans++;
}
}
cout << ans;
return 0;
}
但是如果m的数据范围变成
我们这个做法是会超时的,那么正确的解法是什么呢
但是要注意的是我们这么转换的话,其实会放大我们的图,会出现四个不存在的点,且我们的坐标可能出现负数,故我们也要进行偏移处理
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
const int N = (int)6005;
int c[N][N];
int n,m;
int main(){
cin >> n >> m;
for(int i=1;i<=m;i++){
int x,y,r;
cin >> x >> y >> r;
int nx = x+y, ny = x-y+3000;
// 接着进行二维差分
c[max(nx-r,1)][max(ny-r,1)] ^= 1;
c[min(nx+r+1,6000)][min(ny+r+1,6000)]^=1;
c[min(nx+r+1,6000)][max(ny-r,1)]^=1;
c[max(nx-r,1)][min(ny+r+1,6000)]^=1;
}
int ans = 0;
for(int i=1;i<=6000;i++){
for(int j=1;j<=6000;j++){
c[i][j] = c[i][j]^c[i-1][j-1]^c[i-1][j]^c[i][j-1];
int x = (i+j-3000)/2,y = (i-j+3000)/2;
if(c[i][j]&&(i&1)==(j&1)&&x>0&&x<=n&&y>0&&y<=n)
ans++;
}
}
cout << ans;
return 0;
}
有一个细节需要处理,那就是如何知道我们这个点是不是之前存在的呢,通过 (i&1)==(j&1) 就可以判断,二者的奇偶性必须相同