洛谷U4859matrix[单调栈]
题目描述
给一个元素均为正整数的矩阵,上升矩阵的定义为矩阵中每行、每列都是严格递增的。
求给定矩阵中上升子矩阵的数量。
输入输出格式
输入格式:
第一行两个正整数n、m,表示矩阵的行数、列数。
接下来n行,每行m个正整数表示矩阵中的元素。
输出格式:
一个数表示数量。
输入输出样例
输入样例#1:
4 4 1 2 3 4 2 3 4 5 3 4 5 6 4 5 6 7
输出样例#1:
100
出题人的题解是O(n3)
感觉可以用单调栈做O(n2),果真可以
和仓鼠那道比较像
只是需要维护两个tot,一个是只考虑上下单增,另一个tot2同时考虑左右单增,合并时只能用tot2
如果tot>tot2还要给这个节点再加一个
// // main.cpp // luoguU4859 // // Created by Candy on 10/10/16. // Copyright © 2016 Candy. All rights reserved. // #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const int N=355; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x; } int n,m,a[N][N];// 0<a[i][j] struct data{ int l,h; }st[N]; int top=0,tot[N],tot2[N]; ll ans=0; int main(int argc, const char * argv[]) { n=read();m=read(); memset(a,-1,sizeof(a)); for(int i=1;i<=n;i++){ top=0; ll cnt=0; for(int j=1;j<=m;j++){ a[i][j]=read(); if(a[i][j]<=a[i-1][j]) tot[j]=tot2[j]=0; tot[j]++;tot2[j]++; if(a[i][j]<=a[i][j-1]){top=0;cnt=0;tot2[j]=0;} data tmp; tmp.h=tot2[j]; if(tot[j]==tot2[j]) tmp.l=1; else tmp.l=0; while(top&&st[top].h>=tmp.h){ tmp.l+=st[top].l; cnt-=st[top].l*st[top].h; top--; } st[++top]=tmp; cnt+=tmp.l*tmp.h; if(tot[j]>tot2[j]){ cnt+=1*tot[j]; st[++top].h=tot[j]; st[top].l=1; } ans+=cnt; //printf("h %d %d %d %d\n",i,j,tot[j],tot2[j]); //printf("i %d %d %d %d\ncnt %d\n",i,j,tmp.l,tmp.h,cnt); } //printf("ans %d\n",ans); } printf("%lld",ans); return 0; }
Copyright:http://www.cnblogs.com/candy99/