三矩形覆蓋問題啊……不過據說FJOI還出過雙圓覆蓋問題?node
一行,輸出最小的L值。spa
4
0 1
0 -1
1 0
-1 0code
1blog
1 <= N <= 20000,座標絕對值 <= 10^9,保證不會有2棵樹的座標相同。ip
三正方形有些複雜,咱們不如先從單正方形,雙正方形入手。單正方形的答案就是max(橫座標極差,縱座標極差)。get
雙正方形很差貪心,因此咱們二分一下答案,判斷兩個正方形可否覆蓋全部點。string
咱們就思考一下,這兩個正方形放在哪裏,才能儘可能覆蓋全部點。it
發現覆蓋的形式不外乎兩種狀況,一種是 一個在左上一個在右下 ,另外一種是 一個在右上一個在左下。io
假設是 一個在左上一個在右下 的狀況,處於左上方的正方形必定要蓋住橫座標最左的和縱座標最上的點,由於另外一個正方形不會幫你幹這件事。ast
同理,處於右下方的正方形也同樣。
因此,兩個正方形放置的位置也就肯定了,剩下的事情就是O(n)掃一遍判斷是否在正方形內了。
那麼三正方形其實也是極其相似的作法。
仍是二分答案,考慮三個正方形的放法,發現狀況有一點多。
可是有一點必定是不變的,那就是一定有一個正方形,處於左上、右上、左下、右下的其中一個角!
那麼咱們就枚舉這個角,刪去這個角內的點,剩下的,就是一個雙正方形覆蓋問題!
時間複雜度O(nlogn)。
#include <cstdio> #include <algorithm> #include <cstring> #define MN 20005 #define INF 0x3FFFFFFF using namespace std; struct node{int x,y;}a[MN]; int b[MN]; int bin,n,L,R; inline int read() { int n=0,f=1; char c=getchar(); while (c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();} while (c>='0' && c<='9') {n=n*10+c-'0'; c=getchar();} return n*f; } bool cov(int len) { if (!bin) return true; register int i,lm,rm,dm,um; lm=dm=INF; rm=um=-INF; for (i=1;i<=bin;++i) lm=min(lm,a[b[i]].x),rm=max(rm,a[b[i]].x), dm=min(dm,a[b[i]].y),um=max(um,a[b[i]].y); for (i=1;i<=bin;++i) if (!(a[b[i]].x<=lm+len&&a[b[i]].y<=dm+len ||a[b[i]].x>=rm-len&&a[b[i]].y>=um-len)) break; if (i>bin) return true; for (i=1;i<=bin;++i) if (!(a[b[i]].x<=lm+len&&a[b[i]].y>=um-len ||a[b[i]].x>=rm-len&&a[b[i]].y<=dm+len)) break; if (i>bin) return true; return false; } void del(int lm,int dm,int rm,int um) { register int i; for (bin=0,i=1;i<=n;++i) if (a[i].x<lm||a[i].x>rm||a[i].y<dm||a[i].y>um) b[++bin]=i; } int main() { register int i,lm,rm,dm,um; lm=dm=INF; rm=um=-INF; n=read(); for (i=1;i<=n;++i) a[i].x=read(),a[i].y=read(), lm=min(lm,a[i].x),rm=max(rm,a[i].x), dm=min(dm,a[i].y),um=max(um,a[i].y); L=0; R=max(um-dm,rm-lm); while (L<R) { int mid=L+R>>1; for (i=1;i<=4;++i) { if (i==1) del(lm,dm,lm+mid,dm+mid); else if (i==2) del(lm,um-mid,lm+mid,um); else if (i==3) del(rm-mid,dm,rm,dm+mid); else if (i==4) del(rm-mid,um-mid,rm,um); if (cov(mid)) break; } if (i<=4) R=mid; else L=mid+1; } printf("%d",L); }
沒有想到小C能搶到這題的一個rank1,先放張圖留念,指不定哪天就被某大神艹下去了。