单调栈可以维护一个长度递增的序列,当新加入的元素不递增时,会把前面的元素截断,使其保持递增
由于截断之后大量的元素长度相同,所以没有必要把所有所有元素压入栈,只需将这些元素压缩成一个(用矩阵块和表示!),记录个数,放入栈既可。
//#pragma comment(linker, "/STACK:102400000") #include<cstdlib> #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<map> #include<list> #include<queue> #include<vector> #define tree int o,int l,int r #define lson o<<1,l,mid #define rson o<<1|1,mid+1,r #define lo o<<1 #define ro o<<1|1 #define ULL unsigned long long #define LL long long #define inf 0x7fffffff #define eps 1e-7 #define N 3009 using namespace std; int m,n,T,t,x,y,k; LL a[N][N],sum[N][N]; LL q[N],top,len[N],d[N]; LL sumhe(int x,int y,int a,int b) { return sum[x][y]-sum[a][y]-sum[x][b]+sum[a][b]; } int main() { #ifndef ONLINE_JUDGE freopen("ex.in","r",stdin); #endif scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); for(int i=1; i<=n; i++) for(int j=1; j<=m; ++j) { scanf("%I64d",&a[i][j]); sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j]; } memset(len,0,sizeof(len)); LL ans=0; for(int i=1; i<=n; i++) { top=0; d[0]=0; q[top++]=0; for(int j=1; j<=m; ++j) { if(a[i][j]>=k)len[j]++; else len[j]=0; while(top>0&&len[j]<len[q[top-1]]) top--; int pre=q[top-1]; if(len[j]==0) d[j]=0; else d[j]=d[pre]+sumhe(i,j,i-len[j],pre); ans=max(ans,d[j]); q[top++]=j; } } printf("%I64d ",ans); } return 0; }