我是一个小沙比,爆零本领强~
T1
看起来是一道很捞的、做过无数遍的区间最大值。
直接$O(n^3)$做一做就完了……
具体做法就是预处理每行的前缀和,然后二重循环枚举一个固定的列区间,再用单调队列的思想,从第一行不停向下扩展行区间,如果矩阵内总和$\gt k$ 了就从行区间顶部不停删行,删到矩阵内总和$\le k$ 为止。每当矩阵总和满足限制时,更新矩阵面积最大值即可。
当然如果你很想大战$T1$的话,可以写个$O(n^2*log(n^2))$的主席树?
1 #include<cmath> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define N 501 8 using namespace std; 9 inline int read(){ 10 int x=0; bool f=1; char c=getchar(); 11 for(;!isdigit(c);c=getchar()) if(c=='-') f=0; 12 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0'); 13 if(f) return x; 14 return 0-x; 15 } 16 int n,m,e[N][N],sum[N][N],x,ans; 17 int main(){ 18 n=read()+1,m=read(); 19 int i,j,k,go; 20 for(i=1;i^n;++i) 21 for(j=1;j^n;++j) 22 sum[i][j]=sum[i][j-1]+read(); 23 for(i=1;i^n;++i){ 24 for(j=i;j^n;++j){ 25 x=0, go=1; 26 for(k=1;k^n;++k){ 27 x+=sum[k][j]-sum[k][i-1]; 28 while(x>m) x-=sum[go][j]-sum[go][i-1], ++go; 29 ans=max(ans,(j-i+1)*(k-go+1)); 30 } 31 } 32 } 33 printf("%d\n",ans); 34 return 0; 35 }