Kattis - zoninghouses-K - Zoning Houses (线段树&&思路)

版权声明:沃斯里德小浩浩啊 https://blog.csdn.net/Healer66/article/details/83572750

链接:

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

猜你喜欢

转载自blog.csdn.net/Healer66/article/details/83572750