二分为何错误?
  • 板块P2706 巧克力
  • 楼主SJZ08
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/9/25 20:20
  • 上次更新2024/9/25 22:10:48
查看原帖
二分为何错误?
879242
SJZ08楼主2024/9/25 20:20

我的思路是这样的:

遍历每个点,用二分向上下左右扩展找到最大能到的没被虫蛀的点
再遍历每个点,先让他再上下方向全满,然后用二分左右找看有没有可以接上的,统计一次答案
然后让他左右方向拉满,用二分上下找看有没有接上的,统计一次答案
但是只有60分

代码:

#include <iostream>
#include <algorithm>
using namespace std;
const int N=305;
int a[N][N],s[N][N],v[N][N];
int U[N][N],D[N][N],L[N][N],R[N][N];
int querys(int x1,int y1,int x2,int y2) {
	return s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
}
int queryv(int x1,int y1,int x2,int y2) {
	return v[x2][y2]-v[x2][y1-1]-v[x1-1][y2]+v[x1-1][y1-1];
}
int main() {
	int n,m;
	scanf("%d %d",&n,&m);
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			scanf("%d",&a[i][j]);
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
			v[i][j]=v[i-1][j]+v[i][j-1]-v[i-1][j-1]+(a[i][j]==0?1:0);
		}
	}
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			int l=1,r=i-1;
			U[i][j]=D[i][j]=i;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(mid,j,i,j)==0) {
					U[i][j]=min(U[i][j],mid);
					r=mid-1;
				}else {
					l=mid+1;
				}
			}
			l=i+1,r=n;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(i,j,mid,j)==0) {
					D[i][j]=max(D[i][j],mid);
					l=mid+1;
				}else {
					r=mid-1;
				}
			}
			L[i][j]=R[i][j]=j;
			l=1,r=j-1;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(i,mid,i,j)==0) {
					L[i][j]=min(L[i][j],mid);
					r=mid-1;
				}else {
					l=mid+1;
				}
			}
			l=j+1,r=m;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(i,j,i,mid)==0) {
					R[i][j]=max(R[i][j],mid);
					l=mid+1;
				}else {
					r=mid-1;
				}
			}
		}
	}
	int ans=0;
	for (int i=1;i<=n;i++) {
		for (int j=1;j<=m;j++) {
			if (a[i][j]==0) continue;
			int l=1,r=j-1,ansl=j,ansr=j,ansu=i,ansd=i;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(U[i][j],mid,D[i][j],j)==0) {
					ansl=min(ansl,mid);
					r=mid-1;
				}else {
					l=mid+1;
				}
			}
			l=j+1,r=m;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(U[i][j],j,D[i][j],mid)==0) {
					ansr=max(ansr,mid);
					l=mid+1;
				}else {
					r=mid-1;
				}
			}
			ans=max(ans,querys(U[i][j],ansl,D[i][j],ansr));
			l=1,r=i-1;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(mid,L[i][j],i,R[i][j])==0) {
					ansu=min(ansu,mid);
					r=mid-1;
				}else {
					l=mid+1;
				}
			}
			l=i+1,r=n;
			while (l<=r) {
				int mid=(l+r)>>1;
				if (queryv(i,L[i][j],mid,R[i][j])==0) {
					ansd=max(ansd,mid);
					l=mid+1;
				}else {
					r=mid-1;
				}
			}
			ans=max(ans,querys(ansu,L[i][j],ansd,R[i][j]));
		}
	}
	printf("%d",ans);
	return 0;
}
2024/9/25 20:20
加载中...