Usaco Training Section 5.3 Big Barn
阿新 • • 發佈:2018-11-12
在一個n*n的方格中找出最大的不包含障礙的正方形。(n<=1000,障礙數<=10000)
看起來好像有點難,不能隨便列舉。但仔細一想,可以發現:最大的正方形中至少有一個的一邊靠著障礙。於是我們只需列舉每個障礙上下左右最大的正方形是多少。
至於某一個方向最大的正方形怎麼求,我們以右邊的為例。我們先預處理每一列所有障礙的橫座標,排序。對於當前障礙在x行y列,j從y+1列向右推,每次用y列中最接近x的橫座標更新l,r,用l和r更新maxl和minr,正方形的邊長為min(minr-maxl,j-b[i].y)。一個優化:當minr-maxl<j-b[i].y時可推出,因為再往右推的結果<=當前的minr-maxl。
注意:多餘陣列不要亂開,usaco training給的空間只有16MB
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define inf 2147483647 #define mp make_pair #define pii pair<int,int> #define pb push_back using namespace std; inline int read(){ int x=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x; } struct node{ int x,y; }b[10001]; int a[1001][1001]; vector<int> x[1001],y[1001]; inline bool cmp(node c,node d){ return c.x<d.x; } inline bool cmp2(node c,node d){ return c.y<d.y; } int main() { freopen("bigbrn.in","r",stdin); freopen("bigbrn.out","w",stdout); int n=read(),m=read(); for(int i=1;i<=m;++i) b[i].x=read(),b[i].y=read(),a[b[i].x][b[i].y]=1; sort(b+1,b+m+1,cmp); for(int i=1;i<=m;++i) x[b[i].y].pb(b[i].x); sort(b+1,b+m+1,cmp2); for(int i=1;i<=m;++i) y[b[i].x].pb(b[i].y); int ans=0; for(int i=1;i<=m;++i){ int j=b[i].y+1,ml,mr; ml=0,mr=n+1; while(1){ if(j>n) break; int pos,sz=x[j].size(),l,r; if(sz==0) l=1,r=n; else{ pos=lower_bound(x[j].begin(),x[j].end(),b[i].x)-x[j].begin(); if(pos==0) l=1,r=x[j][0]-1; else if(pos==sz) l=x[j][pos-1]+1,r=n; else l=x[j][pos-1]+1,r=x[j][pos]-1; } ml=max(ml,l);mr=min(mr,r); ans=max(ans,min(mr-ml+1,j-b[i].y)); if(mr-ml+1<j-b[i].y) break; ++j; } j=b[i].y-1;ml=0,mr=n+1; while(1){ if(j<1) break; int pos,sz=x[j].size(),l,r; if(sz==0) l=1,r=n; else{ pos=lower_bound(x[j].begin(),x[j].end(),b[i].x)-x[j].begin(); if(pos==0) l=1,r=x[j][0]-1; else if(pos==sz) l=x[j][pos-1]+1,r=n; else l=x[j][pos-1]+1,r=x[j][pos]-1; } ml=max(ml,l);mr=min(mr,r); ans=max(ans,min(mr-ml+1,b[i].y-j)); if(mr-ml+1<b[i].y-j) break; --j; } j=b[i].x+1;ml=0,mr=n+1; while(1){ if(j>n) break; int pos,sz=y[j].size(),l,r; if(sz==0) l=1,r=n; else{ pos=lower_bound(y[j].begin(),y[j].end(),b[i].y)-y[j].begin(); if(pos==0) l=1,r=y[j][0]-1; else if(pos==sz) l=y[j][pos-1]+1,r=n; else l=y[j][pos-1]+1,r=y[j][pos]-1; } ml=max(ml,l);mr=min(mr,r); ans=max(ans,min(mr-ml+1,j-b[i].x)); if(mr-ml+1<j-b[i].x) break; ++j; } j=b[i].x-1;ml=0,mr=n+1; while(1){ if(j<1) break; int pos,sz=y[j].size(),l,r; if(sz==0) l=1,r=n; else{ pos=lower_bound(y[j].begin(),y[j].end(),b[i].y)-y[j].begin(); if(pos==0) l=1,r=y[j][0]-1; else if(pos==sz) l=y[j][pos-1]+1,r=n; else l=y[j][pos-1]+1,r=y[j][pos]-1; } ml=max(ml,l);mr=min(mr,r); ans=max(ans,min(mr-ml+1,b[i].x-j)); if(mr-ml+1<b[i].x-j) break; --j; } } printf("%d\n",ans); return 0; }