大致题意,给出n组描述,和k。如图,是k=3时的图(请忽略坐标)
描述会标明(x,y)坐标是B/W
然后问你自己确定坐标原点,使得满足得要求最多,输出最多满足多少要求
数据范围见上
显然第一反应O(N^2*k)超级大暴力
这个超级大暴力可以通过类似滑块的方式简化到O(N*k)然后有人就这样过了
我简单讲一下我想的O(k^2)
每个点,其实就对应着其横纵坐标%(2*k)的点
然后横(纵)(注意是或,不是且,都+k等于没有反色)坐标+k可以反色
这样,我们就可以得到一个(2*k)*(2*k)的矩形,而且它们都要求同色
然后求二维前缀和(容斥定理)
然后O(k^2)枚举矩形
如图,划分为五个区域,另外四个区域直接n-即可
当然,求矩形内有几个点一样的容斥定理
上代码吧
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int K=3005;
int x[K][K];
int n,k;
int getsize(int x1,int y1,int x2,int y2){
return x[x2][y2]-x[x2][y1]-x[x1][y2]+x[x1][y1];
}
int main()
{
scanf("%d%d",&n,&k);
int a,b;
char c;
for(int i=1;i<=n;i++){
scanf("%d%d %c",&a,&b,&c);
a%=2*k,b%=2*k;
if(c=='W')
b+=k;
x[a%(2*k)+1][b%(2*k)+1]++;
}
for(int i=1;i<=2*k;i++)
for(int j=1;j<=2*k;j++)
x[i][j]=x[i][j]+(x[i-1][j]+x[i][j-1]-x[i-1][j-1]);
int ans=0,sum;
for(int i=1;i<=k;i++)
for(int j=1;j<=k;j++){
sum=getsize(0,0,i,j);
sum+=getsize(i,j,k+i,k+j);
sum+=getsize(k+i,k+j,2*k,2*k);
sum+=getsize(k+i,0,2*k,j);
sum+=getsize(0,k+j,i,2*k);
sum=max(n-sum,sum);
ans=max(ans,sum);
}
printf("%d\n",ans);
}