ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

求区间内相差最小的两个数的差

分sqrt(n)块,预处理两个数在块内,以及一个数在块内一个数在零散部分的情况,询问时归并排序处理两个数都在零散部分的情况,时间复杂度$O((n+q)\sqrt{n})$。

#include<bits/stdc++.h>
const int N=100007,inf=0x7fffffff;
char ib[N*30],*ip=ib;
int _(){
    int x=0;
    while(*ip<48)++ip;
    while(*ip>47)x=x*10+*ip++-48;
    return x;
}
int abs(int x){return x>0?x:-x;}
int min(int a,int b){return a<b?a:b;}
void mins(int&a,int b){if(a>b)a=b;}
int n,m,B,bid[N],ls[333],rs[333],mb[N],bc=0,f[N][333],ans,bb[333][333],av[N];
struct pos{
    int x,y;
    bool operator<(const pos&w)const{return y<w.y;}
}as[N],bs[N];
void block(int l,int r,int c){
    std::sort(as+l,as+r+1);
    ls[c]=l,rs[c]=r;
    for(int i=l;i<=r;++i)bid[i]=c,av[i]=as[i].y;
    bb[c][c]=inf;
    for(int i=l+1;i<=r;++i)mins(bb[c][c],av[i]-av[i-1]);
}
void get(int l,int r){
    int R=rs[bid[l]],xp=0,xs[333];
    for(int i=ls[bid[l]];i<=R;++i)if(as[i].x>=l&&as[i].x<=r)xs[xp++]=as[i].y;
    for(int i=1;i<xp;++i)mins(ans,xs[i]-xs[i-1]);
}
void get(int l,int pl,int pr,int r){
    int L=bid[l],R=bid[r],ys[333],yp=0,yl=0,zs[666],zp=0;
    for(int i=ls[L];i<=rs[L];++i)if(as[i].x>=l)ys[yp++]=as[i].y;
    ys[yp]=inf;
    for(int i=ls[R];i<=rs[R];++i)if(as[i].x<=r){
        int y=as[i].y;
        for(;ys[yl]<y;zs[zp++]=ys[yl++]);
        zs[zp++]=y;
    }
    for(;yl<yp;zs[zp++]=ys[yl++]);
    for(int i=1;i<zp;++i)mins(ans,zs[i]-zs[i-1]);
}
int cal(int l,int r){
    int zs[666],zp=0;
    bb[l][r]=min(bb[l+1][r],bb[l][r-1]);
    int*al=av+ls[l],*ar=av+rs[l]+1;
    int*bl=av+ls[r],*br=av+rs[r]+1;
    while(al!=ar&&bl!=br)zs[zp++]=*al<*bl?*al++:*bl++;
    while(al!=ar)zs[zp++]=*al++;
    while(bl!=br)zs[zp++]=*bl++;
    for(int i=1;i<zp;++i)mins(bb[l][r],zs[i]-zs[i-1]);
}
int main(){
    fread(ib,1,sizeof(ib),stdin);
    n=_(),m=_();
    B=sqrt(n);
    for(int i=1;i<=n;++i){
        int y=_();
        as[i]=bs[i]=(pos){i,y};
    }
    for(int i=1;i<=n;i+=B)block(i,min(i+B-1,n),++bc);
    for(int l=bc;l;--l){
        for(int r=l+1;r<=bc;++r)cal(l,r);
    }
    std::sort(bs+1,bs+n+1);
    for(int i=1;i<=bc;++i)mb[i]=-inf/2;
    for(int i=1;i<=n;++i){
        int x=bs[i].x,y=bs[i].y;
        for(int j=1;j<=bc;++j)f[x][j]=y-mb[j];
        mb[bid[x]]=y;
    }
    for(int i=1;i<=bc;++i)mb[i]=inf;
    for(int i=n;i;--i){
        int x=bs[i].x,y=bs[i].y;
        for(int j=1;j<=bc;++j)mins(f[x][j],mb[j]-y);
        for(int j=bid[x]+2;j<=bc;++j)mins(f[x][j],f[x][j-1]);
        for(int j=bid[x]-2;j>=1;--j)mins(f[x][j],f[x][j+1]);
        mb[bid[x]]=y;
    }
    while(m--){
        int l=_(),r=_();
        int L=bid[l],R=bid[r];ans=inf;
        if(L==R)get(l,r);
        else{
            int pl=rs[L],pr=ls[R];
            get(l,pl,pr,r);
            if(R-L>1){
                mins(ans,bb[++L][--R]);
                for(int i=l;i<=pl;++i)mins(ans,f[i][R]);
                for(int i=pr;i<=r;++i)mins(ans,f[i][L]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted on 2017-09-18 18:03  nul  阅读(222)  评论(0编辑  收藏  举报