求助,子矩形都求对了,然而子正方形挂了....

P1169 [ZJOI2007] 棋盘制作

本帖终结. 感谢 @[longyun](/space/show?uid=28703) 的帮助. 修改了and的初值处理....如图 ```cpp #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <stack> using namespace std; int read(){ int x=0,f=1;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch>'9'||ch<'0'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return x*f; } const int N=2000+10; const int P=15; int n,m,a[N][N],flag; int ans0,ans1; int l[N][N],up[N][N],down[N][N],pre[N][2]; int st_min[N][N][P],st_and[N][N][P],lg2[N]; void init(){ for(int i=2;i<=n;i++) lg2[i]=lg2[i>>1]+1; for(int j=1;j<=m;j++) for(int k=1;k<P;k++) for(int i=1;(i+(1<<k)-1)<=n;i++){ st_min[j][i][k]=min(st_min[j][i][k-1],st_min[j][i+(1<<(k-1))][k-1]); st_and[j][i][k]=st_and[j][i][k-1]&st_and[j][i+(1<<(k-1))][k-1]; } } inline int qmin(int i,int l,int r){ if(l>r) return -1; int t=lg2[r-l+1]; return min(st_min[i][l][t],st_min[i][r-(1<<t)+1][t]); } // st[i][j][k] // col i, [j,j+2^k) inline int qand(int i,int l,int r){ if(l>r) return 1; int t=lg2[r-l+1]; return st_and[i][l][t]&st_and[i][r-(1<<t)+1][t]; } inline int getup(int i,int j){ int l=1,r=i,ans=0,mid=0; while(l<=r){ mid=(l+r)>>1; if(qmin(j,mid,i)==::l[i][j]&&qand(j,mid+1,i)){ ans=mid; r=mid-1; }else l=mid+1; } return ans; } inline int getdown(int i,int j){ int l=i,r=n,ans=0,mid=0; while(l<=r){ mid=(l+r)>>1; if(qmin(j,i,mid)==::l[i][j]&&qand(j,i+1,mid)){ ans=mid; l=mid+1; }else r=mid-1; } return ans; } void solve(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(j-1>0&&(a[i][j]^a[i][j-1])) l[i][j]=l[i][j-1]+1; else l[i][j]=1; // st[i][j][k] // col i, [j,j+2^k) st_and[j][i][0]=(pre[j][a[i][j]]==0||(pre[j][a[i][j]]>0&&pre[j][a[i][j]]!=i-1)); st_min[j][i][0]=l[i][j]; pre[j][a[i][j]]=i; } init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ up[i][j]=getup(i,j); down[i][j]=getdown(i,j); //printf("pos (%d,%d), left=%d, up,down=(%d,%d)\n",i,j,l[i][j],up[i][j],down[i][j]); int len=min(l[i][j],down[i][j]-up[i][j]+1); ans0=max(ans0,len*len); ans1=max(ans1,l[i][j]*(down[i][j]-up[i][j]+1)); } } int main(){ n=read();m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(); solve(); cout<<ans0<<endl<<ans1<<endl; return 0; } ```
by hehelego @ 2018-12-14 11:43:14


没必要这么麻烦吧 @[呵呵lego](/space/show?uid=15295)
by Celebrate @ 2019-01-07 13:17:59


|