Zoning Houses Kattis 多组记录线段树/ST表

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

猜你喜欢

转载自blog.csdn.net/qq_40772692/article/details/83624133