1. 程式人生 > >Kattis - zoninghouses-K - Zoning Houses (線段樹&&思路)

Kattis - zoninghouses-K - Zoning Houses (線段樹&&思路)

連結:

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);
    }
}