Description
Input
Output
一行表示答案
Sample Input
3 3 2
1 2 3
4 5 6
7 8 9
Sample Output
112
Data Constraint
赛时
考试时想了很多很多很多很多……(此处省略很多很多)的方法。
反正最后要不就是少考虑一种情况,要不就是时间复杂度极其不优秀。
最后一个小时全速码力,怒肝
O
(
n
3
l
o
g
n
)
O(n^3\ log\ n)
O(n3 log n)
结果头脑发热,线段树都打错好几次。
最后获得了0分好成绩。
题解
然鹅时间复杂度是长这样的:
O
(
(
n
−
k
)
2
∗
k
l
o
g
(
n
2
)
)
O((n-k)^2*k\ log\ (n^2))
O((n−k)2∗k log (n2))
后面的
l
o
g
log
log其实20不到,主要是前面的复杂度。
然后求导(不是我求的)可以发现,当k取166时复杂度达到最大为3s,而题目给了5s。
我们发现,只要常数够小就可以水过去。
考虑这样怎么做。
首先,对于一个给定的矩阵怎么求。我们发现,绝对值直接搞不好搞。
然后我们可以弄一个树状数组(离散化),维护两个东东,一个是和,一个是数量。
对于一个数p,直接求出比之小的数的和和个数。然后用总和减去即可。
那么我们先
O
(
k
2
l
o
g
n
2
)
O(k^2\ log\ n^2)
O(k2 log n2)地求出最左边的矩阵的树状数组。
然后每次就往右边平移,每次直接树状数组修改把最左边一列给删掉,然后把最右边的一列加入树状数组。
那么这样就可以十分暴力简单地求出答案了。
然鹅每次求最左边的矩阵所耗时似乎有点多,那么我们可以考虑蛇形走位来维护树状数组。
那么往右平移做完第一行时,我们就往下平移一行,然后再向左平移。依次往复。
这样就是稳定的 O ( ( n − k ) 2 ∗ k l o g ( n 2 ) ) O((n-k)^2*k\ log\ (n^2)) O((n−k)2∗k log (n2))
似乎有个 O ( n 2 l o g n ) O(n^2\ log\ n) O(n2 log n)的神奇做法,然鹅我不废。
代码
跑了4s左右。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
const long long mo=10007;
const int maxn=501;
int n,m,a[maxn][maxn],b[maxn*maxn],c[maxn][maxn],rot[maxn*maxn],answer,x[maxn*maxn],y[maxn*maxn],cnt,k,gs,up,gg;
long long tree[maxn*maxn*10],jl,ans,sum,p,zh;
int le[maxn*maxn*10],re[maxn*maxn*10],op[maxn*maxn*10];
void qsort(int l,int r)
{
int i=l;int j=r;
int m=b[(i+j)/2];
while (i<=j)
{
while (b[i]<m) i++;
while (b[j]>m) j--;
if (i<=j)
{
swap(x[i],x[j]);
swap(y[i],y[j]);
swap(b[i],b[j]);
i++;j--;
}
}
if (l<j) qsort(l,j);
if (r>i) qsort(i,r);
}
int lowbit(int x)
{
return x&(-x);
}
void modify(int i,long long k,long long g)
{
while (i<=up)
{
tree[i]=(tree[i]+k*g)%mo;
op[i]=(op[i]+g)%mo;
i+=lowbit(i);
}
}
void getans(int i)
{
int kk=0;
while (i>0)
{
jl=(jl+tree[i])%mo;
gg=(gg+op[i])%mo;
kk=lowbit(i);
i-=kk;
}
}
int main()
{
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
gs++;b[gs]=a[i][j];x[gs]=i;y[gs]=j;
}
}
qsort(1,gs);
int l=0;
for (int i=1;i<=gs;i++)
{
if (b[i]!=b[i-1]) l++;
c[x[i]][y[i]]=l;
}
up=l;
zh=0;
sum=0;ans=0;
for (register int j=1;j<=k;j++)
{
int ppp=0;
for (register int l=1;l<=k;l++)
{
p=a[j][l];
modify(c[j][l],p,1);
sum+=p;zh++;
jl=0;gg=0;
p=a[j][l];
getans(c[j][l]);
ans=(ans+gg*p%mo-jl+mo)%mo;
ans=(ans+(sum-jl+mo)%mo-(zh-gg)*p%mo+mo)%mo;
}
}
answer=(answer+ans*2%mo+mo)%mo;
for (register int i=1;i<=(n-k+1);i++)
{
// printf("%lld\n",answer);
if (i%2==1)
{
for (register int j=2;j<=m-k+1;j++)
{
for (register int l=i;l<=k+i-1;l++)
{
jl=0;gg=0;
p=a[l][j-1];
getans(c[l][j-1]);
ans=(ans-gg*p%mo+jl+mo)%mo;
ans=(ans-(sum-jl+mo)%mo+(zh-gg)*p%mo+mo)%mo;
p=a[l][j-1];
modify(c[l][j-1],p,-1);
sum=(sum-p+mo)%mo;zh--;
}
for (register int l=i;l<=k+i-1;l++)
{
p=a[l][j+k-1];
modify(c[l][j+k-1],p,1);
sum=(sum+p+mo)%mo;zh++;
jl=0;gg=0;
p=a[l][j+k-1];
getans(c[l][j+k-1]);
ans=(ans+gg*p%mo-jl+mo)%mo;
ans=(ans+(sum-jl+mo)%mo-(zh-gg)*p%mo+mo)%mo;
}
answer=(answer+2*ans+mo)%mo;
}
if (i<n-k+1)
{
for (register int l=m-k+1;l<=m;l++)
{
jl=0;gg=0;
p=a[i][l];
getans(c[i][l]);
ans=(ans-gg*p%mo+jl+mo)%mo;
ans=(ans-(sum-jl+mo)%mo+(zh-gg)*p%mo+mo)%mo;
p=a[i][l];
modify(c[i][l],p,-1);
sum=(sum-p+mo)%mo;zh--;
}
for (register int l=m-k+1;l<=m;l++)
{
p=a[i+k][l];
modify(c[i+k][l],p,1);
sum=(sum+p+mo)%mo;zh++;
jl=0;gg=0;
p=a[i+k][l];
getans(c[i+k][l]);
ans=(ans+gg*p%mo-jl+mo)%mo;
ans=(ans+(sum-jl+mo)%mo-(zh-gg)*p%mo+mo)%mo;
}
answer=(answer+2*ans+mo)%mo;
}
}
else
{
for (register int j=m-k;j>=1;j--)
{
for (register int l=i;l<=k+i-1;l++)
{
jl=0;gg=0;
p=a[l][j+k];
getans(c[l][j+k]);
ans=(ans-gg*p%mo+jl+mo)%mo;
ans=(ans-(sum-jl+mo)%mo+(zh-gg)*p%mo+mo)%mo;
p=a[l][j+k];
modify(c[l][j+k],p,-1);
sum=(sum-p+mo)%mo;zh--;
}
for (register int l=i;l<=k+i-1;l++)
{
p=a[l][j];
modify(c[l][j],p,1);
sum=(sum+p+mo)%mo;zh++;
jl=0;gg=0;
p=a[l][j];
getans(c[l][j]);
ans=(ans+gg*p%mo-jl+mo)%mo;
ans=(ans+(sum-jl+mo)%mo-(zh-gg)*p%mo+mo)%mo;
}
answer=(answer+2*ans+mo)%mo;
}
if (i<n-k+1)
{
for (register int l=1;l<=k;l++)
{
jl=0;gg=0;
p=a[i][l];
getans(c[i][l]);
ans=(ans-gg*p%mo+jl+mo)%mo;
ans=(ans-(sum-jl+mo)%mo+(zh-gg)*p%mo+mo)%mo;
p=a[i][l];
modify(c[i][l],p,-1);
sum=(sum-p+mo)%mo;zh--;
}
for (register int l=1;l<=k;l++)
{
p=a[i+k][l];
modify(c[i+k][l],p,1);
sum=(sum+p+mo)%mo;zh++;
jl=0;gg=0;
p=a[i+k][l];
getans(c[i+k][l]);
ans=(ans+gg*p%mo-jl+mo)%mo;
ans=(ans+(sum-jl+mo)%mo-(zh-gg)*p%mo+mo)%mo;
}
answer=(answer+2*ans+mo)%mo;
}
}
}
printf("%lld\n",answer);
}