1。题意:给你n个平面上的点,再给你m个询问,每个询问包括[ l, r ]内的点,让你求出包含这些点在内的最小正方形的边长,你可以忽略这些点内的一个点。
2.分析:如果不忽略点,我们只需要取这些点中的x的最大,最小;y的最大,最小即可判定氛围内的最小正方形变长:max(xmax - xmin , ymax - yin);
现在可以忽略一个点,肯定是忽略比不忽略优,所以我们直接忽略一个点即可。忽略哪个点呢?肯定是这四个最点中的一个。于是枚举去除四个点中一个后的边长的最大值的最小值。
比如,去除xmax后(假设对应点编号为t , 因为无重复点所以编号唯一),就要求x的次大值xmax2,也就是求 [ x , t-1 ] 和 [ t+1,y ]中的 max(xmax1,xmax2)为次大x,则此时最小边长:max(xmax2 - xmain , ymax - yin);
所以对于一次询问,要查询四个最值,去除每个最值后要查询该最值下的次值。
3.代码:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int INF = 2e9 + 7;
const int maxn = 100000 + 7;
P Xmax[maxn<<2],Xmin[maxn<<2],Ymax[maxn<<2],Ymin[maxn<<2];
int x[maxn],y[maxn];
int n,m;
map<P,int> IDx;
map<P,int> IDy;
void pushUp(int root){
Xmax[root] = max(Xmax[root<<1],Xmax[root<<1|1]);
Ymax[root] = max(Ymax[root<<1],Ymax[root<<1|1]);
Xmin[root] = min(Xmin[root<<1],Xmin[root<<1|1]);
Ymin[root] = min(Ymin[root<<1],Ymin[root<<1|1]);
}
void Build(int l,int r,int root){
if(l==r){
scanf("%d%d",&x[l],&y[l]);
Xmax[root] = P(x[l],y[l]);//建树取最值
Xmin[root] = P(x[l],y[l]);
Ymax[root] = P(y[l],x[l]);
Ymin[root] = P(y[l],x[l]);
IDx[P(x[l],y[l])] = l;//每个点一个编号
IDy[P(y[l],x[l])] = l;
return;
}
int mid = (l+r)>>1;
Build(l,mid,root<<1);
Build(mid+1,r,root<<1|1);
pushUp(root);//求区间四个最值
}
P QueryXmax(int L,int R,int l,int r,int root){//查询区间最大x(pair可以直接比较大小,比较键)
if(R<L)return P(-INF,0);
if(L<=l&&R>=r)return Xmax[root];
int mid = (l+r)>>1;
P ans = P(-INF,0);
if(L<=mid)ans = max(ans,QueryXmax(L,R,l,mid,root<<1));
if(R>mid)ans = max(ans,QueryXmax(L,R,mid+1,r,root<<1|1));
return ans;
}
P QueryXmin(int L,int R,int l,int r,int root){//查询区间最小x
if(R<L)return P(INF,0);
if(L<=l&&R>=r)return Xmin[root];
int mid = (l+r)>>1;
P ans = P(INF,0);
if(L<=mid)ans = min(ans,QueryXmin(L,R,l,mid,root<<1));
if(R>mid)ans = min(ans,QueryXmin(L,R,mid+1,r,root<<1|1));
return ans;
}
P QueryYmax(int L,int R,int l,int r,int root){//查询区间最大y
if(R<L)return P(-INF,0);
if(L<=l&&R>=r)return Ymax[root];
int mid = (l+r)>>1;
P ans = P(-INF,0);
if(L<=mid)ans = max(ans,QueryYmax(L,R,l,mid,root<<1));
if(R>mid)ans = max(ans,QueryYmax(L,R,mid+1,r,root<<1|1));
return ans;
}
P QueryYmin(int L,int R,int l,int r,int root){//查询区间最小y
if(R<L)return P(INF,0);
if(L<=l&&R>=r)return Ymin[root];
int mid = (l+r)>>1;
P ans = P(INF,0);
if(L<=mid)ans = min(ans,QueryYmin(L,R,l,mid,root<<1));
if(R>mid)ans = min(ans,QueryYmin(L,R,mid+1,r,root<<1|1));
return ans;
}
int solve(int L,int R){
int res = INF;//取四个最值
P num[] = {QueryXmax(L,R,1,n,1),QueryXmin(L,R,1,n,1),QueryYmax(L,R,1,n,1),QueryYmin(L,R,1,n,1)};
//for(int i = 0;i<4;i++)printf("%d\n",num[i]);
for(int i = 0;i<2;i++){//去除最值
int ix = IDx[num[i]];
P MAXx = max(QueryXmax(L,ix-1,1,n,1),QueryXmax(ix+1,R,1,n,1));//查询去除该点后的四个最值
P MINx = min(QueryXmin(L,ix-1,1,n,1),QueryXmin(ix+1,R,1,n,1));
P MAXy = max(QueryYmax(L,ix-1,1,n,1),QueryYmax(ix+1,R,1,n,1));
P MINy = min(QueryYmin(L,ix-1,1,n,1),QueryYmin(ix+1,R,1,n,1));
res = min(res,max(MAXx.first - MINx.first,MAXy.first - MINy.first));
}
for(int i = 2;i<4;i++){
int iy = IDy[num[i]];
P MAXx = max(QueryXmax(L,iy-1,1,n,1),QueryXmax(iy+1,R,1,n,1));
P MINx = min(QueryXmin(L,iy-1,1,n,1),QueryXmin(iy+1,R,1,n,1));
P MAXy = max(QueryYmax(L,iy-1,1,n,1),QueryYmax(iy+1,R,1,n,1));
P MINy = min(QueryYmin(L,iy-1,1,n,1),QueryYmin(iy+1,R,1,n,1));
res = min(res,max(MAXx.first - MINx.first,MAXy.first - MINy.first));
}
return res;
}
int main()
{
scanf("%d%d",&n,&m);
Build(1,n,1);
while(m--){
int L,R;
scanf("%d%d",&L,&R);
printf("%d\n",solve(L,R));
}
return 0;
}
4.ST表
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
#define INF 0x3f3f3f3f
const int maxn = 100000 + 7;
P Maxx[maxn][20],Maxy[maxn][20],Minx[maxn][20],Miny[maxn][20];
int n,m;
void init(){
for(int j = 1;(1<<j)<=n;j++){
for(int i = 1;i + (1<<j) - 1<=n;i++){
Maxx[i][j] = max(Maxx[i][j-1],Maxx[i + (1<<(j-1)) ][j-1]);
Minx[i][j] = min(Minx[i][j-1],Minx[i + (1<<(j-1)) ][j-1]);
Maxy[i][j] = max(Maxy[i][j-1],Maxy[i + (1<<(j-1)) ][j-1]);
Miny[i][j] = min(Miny[i][j-1],Miny[i + (1<<(j-1)) ][j-1]);
}
}
}
P ST(int l,int r,int i){
if(l > r){
if(i==1||i==3)return P(-INF,0);
else return P(INF,0);
}
//int k = (int)log(r - l + 1.0)/log(2.0);
int k = 0;
while((1<<(k+1))<=r - l + 1)k++;
if(i==1)return max(Maxx[l][k],Maxx[r - (1<<k) + 1][k]);
else if(i==2)return min(Minx[l][k],Minx[r - (1<<k) + 1][k]);
else if(i==3)return max(Maxy[l][k],Maxy[r - (1<<k) + 1][k]);
else if(i==4)return min(Miny[l][k],Miny[r - (1<<k) + 1][k]);
}
int Query(int l,int r,int pos){
int dx = max(ST(l,pos-1,1).first,ST(pos+1,r,1).first) - min(ST(l,pos-1,2).first,ST(pos+1,r,2).first);
int dy = max(ST(l,pos-1,3).first,ST(pos+1,r,3).first) - min(ST(l,pos-1,4).first,ST(pos+1,r,4).first);
return max(dx,dy);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
P px = P(a,i);
P py = P(b,i);
Maxx[i][0] = Minx[i][0] = px;
Maxy[i][0] = Miny[i][0] = py;
}
init();
while(m--){
int l,r;
scanf("%d%d",&l,&r);
int ans = Query(l,r,ST(l,r,1).second);
ans = min(ans,Query(l,r,ST(l,r,2).second));
ans = min(ans,Query(l,r,ST(l,r,3).second));
ans = min(ans,Query(l,r,ST(l,r,4).second));
printf("%d\n",ans);
}
return 0;
}