Kattis - zoninghouses-K - Zoning Houses (線段樹&&思路)
阿新 • • 發佈:2018-11-14
連結:
https://cn.vjudge.net/problem/Kattis-zoninghouses
題意:
給出一些點和詢問,詢問是在a-b這些編號的點中,問刪除最多一個點後,最小可以用多大的正方形包圍它們.
思路:
線段樹維護x,y的最大值和最小值,每次分別找出區間內對應的最大值點的編號,計算去除該點後所用矩形的長度(為剩餘點x最大-x最小和y最大-y最小中較大的一個),最後取最小值.
262150的由來是這樣的. 2^n中大於1e5的第一個數是131072,根據等比數列公式和二叉樹的性質,節點數就大致是兩倍
#include<cstdio> #include<algorithm> using namespace std; typedef pair<int,int> P; const int N = 1e5+10,M = 262150,inf = 1e9+10; int n,m,x,y,ans; P xmi[M],xma[M],ymi[M],yma[M]; void build(int x, int l,int r) { if(l == r) { scanf("%d%d",&xmi[x].first,&ymi[x].first);//first 存座標,second 存編號,與讀入順序一致 xmi[x].second = ymi[x].second = l; xma[x] = xmi[x]; yma[x] = ymi[x]; return; } int mid = (l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); xmi[x]=min(xmi[x<<1],xmi[x<<1|1]);//pair 預設按照first 比較,跟map類似 xma[x]=max(xma[x<<1],xma[x<<1|1]); ymi[x]=min(ymi[x<<1],ymi[x<<1|1]); yma[x]=max(yma[x<<1],yma[x<<1|1]); } P askxmi(int x,int l,int r,int c,int d) { if(c>d)return P(inf,0);//不符合條件時,求最小,那麼返回最大 if(c<=l&&r<=d)return xmi[x]; int mid=(l+r)>>1; P t(inf,0); if(c<=mid)t=askxmi(x<<1,l,mid,c,d); if(d>mid)t=min(t,askxmi(x<<1|1,mid+1,r,c,d)); return t; } P askymi(int x,int l,int r,int c,int d) { if(c>d)return P(inf,0); if(c<=l&&r<=d)return ymi[x]; int mid=(l+r)>>1; P t(inf,0); if(c<=mid)t=askymi(x<<1,l,mid,c,d); if(d>mid)t=min(t,askymi(x<<1|1,mid+1,r,c,d)); return t; } P askxma(int x,int l,int r,int c,int d) { if(c>d)return P(-inf,0); if(c<=l&&r<=d)return xma[x]; int mid=(l+r)>>1; P t(-inf,0); if(c<=mid)t=askxma(x<<1,l,mid,c,d); if(d>mid)t=max(t,askxma(x<<1|1,mid+1,r,c,d)); return t; } P askyma(int x,int l,int r,int c,int d) { if(c>d)return P(-inf,0); if(c<=l&&r<=d)return yma[x]; int mid=(l+r)>>1; P t(-inf,0); if(c<=mid)t=askyma(x<<1,l,mid,c,d); if(d>mid)t=max(t,askyma(x<<1|1,mid+1,r,c,d)); return t; } inline int cal(int x,int y,int z) { return max( max(askxma(1,1,n,x,z-1).first,askxma(1,1,n,z+1,y).first)-min(askxmi(1,1,n,x,z-1).first,askxmi(1,1,n,z+1,y).first) , max(askyma(1,1,n,x,z-1).first,askyma(1,1,n,z+1,y).first)-min(askymi(1,1,n,x,z-1).first,askymi(1,1,n,z+1,y).first) ); //刪除最值後,求最大x-最小x和最大y-最小y,取最大 } int main() { scanf("%d%d",&n,&m); build(1,1,n); while(m--) { scanf("%d%d",&x,&y); ans=cal(x,y,askxmi(1,1,n,x,y).second); ans=min(ans,cal(x,y,askxma(1,1,n,x,y).second)); ans=min(ans,cal(x,y,askymi(1,1,n,x,y).second)); ans=min(ans,cal(x,y,askyma(1,1,n,x,y).second)); printf("%d\n",ans); } }