您的位置:首页 > 其它

【JZOJ5270】【GDOI2018模拟8.14】神奇的矩阵

2017-08-21 07:15 603 查看

Description



Data Constraint





Solution

考场上打了个O(N^3logN)的做法,以为可以水70分,结果出题人非常尽职将其卡至50……

我们考虑若将数从大到小加入,那么每个点的贡献即当前矩形内的点的权值和-该数*矩形内的数的数量。若每个点(i,j)表示一个以(i,j)为左上角的k*k正方形的话,那么当前数(i,j)加入后影响的将会是一个左上角(i-k+1,j-k+1)右下角(i,j)的正方形。我们考虑维护一个二维线段树即可。

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=5e2+5,mo=1e4+7;
struct code1{
ll sum,num,bz,bz1;
}f[maxn*maxn*10];
struct code{
ll x,y,z;
}b[maxn*maxn];
ll a[maxn][maxn];
ll n,m,p,i,t,j,k,l,x,y,z,ans;
bool cmp(code x,code y){
return x.z>y.z;
}
void make(ll v,ll l,ll r){
f[v*2].sum=f[v*2].sum+l*f[v].bz;f[v*2].num+=f[v].bz1*l;
f[v*2+1].sum=f[v*2+1].sum+r*f[v].bz;f[v*2+1].num+=r*f[v].bz1;
f[v*2].bz+=f[v].bz;f[v*2+1].bz+=f[v].bz;
f[v*2].bz1+=f[v].bz1;f[v*2+1].bz1+=f[v].bz1;
f[v].bz=f[v].bz1=0;
}
void insert(ll lx,ll rx,ll ly,ll ry,ll v,ll x,ll y,ll xx,ll yy){
if (lx>=x && rx<=y && ly>=xx && ry<=yy){
t+=f[v].sum;k+=f[v].num;
f[v].bz+=z;f[v].bz1++;
f[v].sum+=z*(rx-lx+1)*(ry-ly+1);
f[v].num+=(rx-lx+1)*(ry-ly+1);
return;
}
if (rx-lx>ry-ly){
ll mid=(rx+lx)/2;
if (f[v].bz1) make(v,(mid-lx+1)*(ry-ly+1),(rx-mid)*(ry-ly+1));
if (lx<=y && mid>=x) insert(lx,mid,ly,ry,v*2,x,y,xx,yy);
if (mid<y && rx>=x) insert(mid+1,rx,ly,ry,v*2+1,x,y,xx,yy);
f[v].sum=f[v*2].sum+f[v*2+1].sum;
f[v].num=f[v*2].num+f[v*2+1].num;
}else{
ll mid=(ry+ly)/2;
if (f[v].bz1) make(v,(mid-ly+1)*(rx-lx+1),(ry-mid)*(rx-lx+1));
if (ly<=yy && mid>=xx) insert(lx,rx,ly,mid,v*2,x,y,xx,yy);
if (mid<yy && ry>=xx) insert(lx,rx,mid+1,ry,v*2+1,x,y,xx,yy);
f[v].sum=f[v*2].sum+f[v*2+1].sum;
f[v].num=f[v*2].num+f[v*2+1].num;
}
}
int main(){
freopen("matrix.in","r",stdin);freopen("matrix.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&p);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
scanf("%lld",&a[i][j]),t++,b[t].x=i,b[t].y=j,b[t].z=a[i][j];
sort(b+1,b+n*m+1,cmp);
for (i=1;i<=n*m;i++){
x=b[i].x;y=b[i].y;z=b[i].z%mo;
t=0;k=0;
insert(1,n,1,n,1,max((ll)1,x-p+1),min(x,n-p+1),max((ll)1,y-p+1),min(y,m-p+1));
ans=(ans+t%mo-k*z%mo+mo)%mo;
}
ans=ans*2%mo;
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: