CF263E Rhombus
发现\(f(x,y)\)即是每个点到此点的距离乘上权值。
考虑挪一下会有什么影响。
往下挪:
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0
0 0 1 2 1 0 0 0 0 0 1 0 0 0 0 0 - - - 0 0
0 1 2 3 2 1 0 --\ 0 0 1 2 1 0 0 --\ 0 - - - - - 0
0 0 1 2 1 0 0 --/ 0 1 2 3 2 1 0 --/ 0 + + + + + 0
0 0 0 1 0 0 0 0 0 1 2 1 0 0 0 0 + + + 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 + 0 0 0
往右挪:
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 - + 0 0
0 0 1 2 1 0 0 0 0 0 1 2 1 0 0 0 - - + + 0
0 1 2 3 2 1 0 --\ 0 0 1 2 3 2 1 --\ 0 - - - + + +
0 0 1 2 1 0 0 --/ 0 0 0 1 2 1 0 --/ 0 0 - - + + 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 - + 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
发现变化的是一片三角形区域,考虑\(duliu\)前后缀处理即可。
代码细节较多,参考价值不大:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e3+5;
const int mod=1e9+7;
int n,m,a[N][N],k;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int s[N],l[N][N],r[N][N],z[N][N],y[N][N];
int sum[N][N],f[N][N],g[N][N];
signed main(){
n=read(),m=read(),k=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=read();
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i][j];
l[i][j]=l[i-1][j-1]+s[i];
}
for(int j=m;j>=1;j--)
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i][j];
r[i][j]=r[i-1][j+1]+s[i];
}
/*
puts("l array is as follow");
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%d ",l[i][j]);
puts("");
}puts("r array is as follow");
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%d ",r[i][j]);
puts("");
}puts("");
*/
memset(s,0,sizeof(s));
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--){
s[j]=s[j+1]+a[i][j];
y[i][j]=y[i-1][j+1]+s[j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
s[j]=s[j-1]+a[i][j];
z[i][j]=z[i-1][j-1]+s[j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
g[i][j]=g[i-1][j]+g[i][j+1]-g[i-1][j+1]+a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[k][k]+=a[i][j]*max(0ll,k-abs(k-i)-abs(k-j));
for(int i=k+1;i<=n-k+1;i++){
sum[i][k]=sum[i-1][k]+r[i+k-1][k]-r[i-1][k+k];
sum[i][k]=sum[i][k]-f[i-1][k+k-1]+f[i-1][k-1];
sum[i][k]=sum[i][k]+l[i+k-2][k-1]-f[i-1][k-1];
sum[i][k]=sum[i][k]-z[i-1][k+k-1]+z[i-k-1][k-1];
sum[i][k]=sum[i][k]+f[i-1][k-1]-f[i-k-1][k-1];
sum[i][k]=sum[i][k]-y[i-1][1]+y[i-k][k];
sum[i][k]=sum[i][k]+g[i-1][k]-g[i-k][k];
}
for(int i=k;i<=n-k+1;i++)
for(int j=k+1;j<=m-k+1;j++){
sum[i][j]=sum[i][j-1]+r[i+k-1][j]-r[i-1][j+k];
sum[i][j]=sum[i][j]-l[i-1][j+k-1];
sum[i][j]=sum[i][j]-l[i+k-1][j-1]+l[i-1][j-k-1];
sum[i][j]=sum[i][j]+r[i-1][j-k];
if(i>k)sum[i][j]=sum[i][j]+l[i-k-1][j-1]-r[i-k-1][j];
//printf("%d %d\n",i,j);
//printf("%d ",r[i+k-1][j]-r[i-1][j+k]-l[i-1][j+k-1]+l[i-k-1][j-1]);
//printf("%d\n",-l[i+k-1][j-1]+l[i-1][j-k-1]+r[i-1][j-k]-r[i-k-1][j]);
}
/*
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%d ",sum[i][j]);
puts("");
}puts("");
*/
int ax,ay,ans=-1;
for(int i=k;i<=n-k+1;i++)
for(int j=k;j<=m-k+1;j++)
if(ans<sum[i][j])ans=sum[i][j],ax=i,ay=j;
printf("%lld %lld\n",ax,ay);
return 0;
}
深深地感到自己的弱小。