洛谷P1736 創意吃魚法
阿新 • • 發佈:2018-12-23
https://www.luogu.org/problemnew/show/P1736
開始自己想:設f(i,j):以(i,j)為左上角的包含(i,j)的最大子正方形大小,則f(i,j)取決於:設t=f(i+1,j+1),(i,j)右以及下方的t個元素最多連續幾個0,可以用二分+字首和。我只會lower/upper_bound,不會手寫二分
求副對角線的話,把矩陣旋轉90°,再求主對角線就行了。或者再寫一個差不多的DP也行。
總複雜度o(n^2logn),不加讀入優化會TLE一個點,加了壓線過。
#include<bits/stdc++.h> using namespace std; int n,m,maxn; int a[2505][2505],b[2505][2505],d[2505][2505]; int row[2505][2505],col[2505][2505]; int Read() { int ans=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { ans=ans*10+ch-'0'; ch=getchar(); } return f*ans; } void solve() { for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) { row[i][j]=row[i][j-1]+a[i][j]; col[j][i]=col[j][i-1]+a[i][j]; } for(int i=n;i>=1;i--) for(int j=m;j>=1;j--) { int t=d[i+1][j+1]; if(row[i][j+t]-row[i][j]==0&&col[j][i+t]-col[j][i]==0&&a[i][j])d[i][j]=t+1; else if(a[i][j]) { d[i][j]=min((int)(upper_bound(&row[i][j]+1,&row[i][j+t]+1,row[i][j])-&row[i][j]),(int)(upper_bound(&col[j][i]+1,&col[j][i+t]+1,col[j][i])-&col[j][i])); } else d[i][j]=0; } for(int i=n;i>=1;i--) for(int j=m;j>=1;j--) maxn=max(maxn,d[i][j]); } int main() { freopen("input.in","r",stdin); n=Read();m=Read(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=Read(); solve(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[j][n-i+1]=a[i][j]; swap(n,m); memset(a,0,sizeof(a));memset(d,0,sizeof(d));memset(row,0,sizeof(row));memset(col,0,sizeof(col)); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=b[i][j]; solve(); printf("%d\n",maxn); return 0; }
看題解,果然和前面那道“最大正方形”很像,可以把logn消掉,先預處理(i,j)向各個方向最多能延伸出去多少個0就行了。別的都一樣。複雜度o(n^2)