• bzoj5052: 繁忙的财政官


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

    分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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    JVM知识体系
    RabbitMQ学习11死信队列(拒绝消息)
    JUC知识体系
    RabbitMQ学习10死信队列(队列达到最大长度)
    Dropdownlist+objectdatasource设定“请选择”默认选项
    sql DATEPART函数使用
    win7 'IIS APPPOOL\Classic .NET AppPool' 登录失败
    sqlserver2000还原数据库时报设备激活错误的解决方法
    vss和vs2008组合搭建源代码管理器
    在配置win7 IIS浏览网站时 检测到在集成的托管管道模式下不适用的ASP.NET设置 的解决方法
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7538170.html
Copyright © 2020-2023  润新知