版权声明:沃斯里德小浩浩啊 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);
}
}