https://acm.ecnu.edu.cn/contest/292/problem/C/
昨天刚做了个二维树状数组子矩阵异或同一个值修改,询问子矩阵异或和的题,有点巧
这题就直接计算每个位置在(a-n+1)*(b-m+1)种情况中,每个格子被照到了多少次,记为sum[i][j]
我们搞个二维差分数组c[i][j],sum[i][j]=c[1,1,i,j]这个前缀矩阵之和
那么在[x0,y0,x1,y1]全部加上1就等于
++c[x0][y0];
--c[x0][y1+1];
--c[x1+1][y0];
++c[x1+1][y1+1];
然后取最大的sum[i][j]为mx,搞个longlong ans算一下正比的答案就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,a,b,cas,k,cnt,tot,mx;
ll ans;
int c[3850][2200];
int sum[3850][2200];
char s[maxl];
bool in[maxl];
inline void prework()
{
scanf("%d%d%d%d",&n,&m,&a,&b);
int x,x0,y0,x1,y1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
if(x)
{
x0=i;y0=j;x1=a-(n-i);y1=b-(m-j);
++c[x0][y0];
--c[x0][y1+1];
--c[x1+1][y0];
++c[x1+1][y1+1];
}
}
mx=0;int tmp;
for(int i=1;i<=a;i++)
{
tmp=0;
for(int j=1;j<=b;j++)
{
tmp+=c[i][j];
sum[i][j]=sum[i-1][j]+tmp;
mx=max(sum[i][j],mx);
}
}
}
inline void mainwork()
{
}
inline void print()
{
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
{
ans=1ll*sum[i][j]*100/mx;
printf("%lld%c",ans," \n"[j==b]);
}
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}