• 4456: [Zjoi2016]旅行者|分治+最短路


    每次将矩形划分成两个部分。枚举中间点跑最短路更新答案,不断递归分治

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<ctime>
    #include<set>
    #include<map>
    #define N 200020
    #define M 200050
    #define inf 1e9
    #define pa pair<int,int>
    using namespace std;
    int sc()
    {
        int i=0; char c=getchar();
        while(c>'9'||c<'0')c=getchar();
        while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
        return i;
    }
    struct W{int x1,x2,y1,y2,p;}a[M],b[M];
    int head[N],nxt[N<<1],lst[N<<1],v[N<<1];
    int px[N],py[N],mark[N],dis[N],ans[M];
    int n,m,tot,Q;
    void insert(int x,int y,int z)
    {
        lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; v[tot]=z;
        lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot; v[tot]=z;
    }
    inline int get(int x,int y)
    {
        return (x-1)*m+y;
    }
    priority_queue<pa,vector<pa>,greater<pa> >q;
    inline bool jud(int x,int nl,int nr,int ml,int mr)
    {
        if(px[x]<nl||px[x]>nr)return 0;
        if(py[x]<ml||py[x]>mr)return 0;
        return 1;
    }
    void dijkstra(int x,int nl,int nr,int ml,int mr)
    {
        for(int i=nl;i<=nr;i++)
            for(int j=ml;j<=mr;j++)
            {
                int p=get(i,j);
                dis[p]=1e9;
                mark[p]=0;
            }
        q.push(make_pair(dis[x]=0,x));
        while(!q.empty())
        {
            int x=q.top().second;q.pop();
            if(mark[x])continue;mark[x]=1;
            for(int i=head[x];i;i=nxt[i])
                if(dis[x]+v[i]<dis[lst[i]]&&jud(lst[i],nl,nr,ml,mr))
                    q.push(make_pair(dis[lst[i]]=dis[x]+v[i],lst[i]));
        }
    }   
    void solve(int nl,int nr,int ml,int mr,int ql,int qr)
    {
        //cout<<nl<<" "<<nr<<" "<<ml<<" "<<mr<<" "<<ql<<" "<<qr<<endl;
        if(ql>qr)return;
        if(nr-nl>mr-ml)
        {
            int mid=nl+nr>>1;
            for(int i=ml;i<=mr;i++)
            {
                dijkstra(get(mid,i),nl,nr,ml,mr);
                for(int j=ql;j<=qr;j++)
                    ans[a[j].p]=min(ans[a[j].p],dis[get(a[j].x1,a[j].y1)]+dis[get(a[j].x2,a[j].y2)]);
            }
            int l=ql-1,r=qr+1;
            for(int i=ql;i<=qr;i++)
                if(a[i].x1<mid&&a[i].x2<mid) b[++l]=a[i];
                else if(a[i].x1>mid&&a[i].x2>mid) b[--r]=a[i];
            for(int i=ql;i<=l;i++) a[i]=b[i];
            for(int i=qr;i>=r;i--) a[i]=b[i];
            solve(nl,mid-1,ml,mr,ql,l); solve(mid+1,nr,ml,mr,r,qr);
        }
        else
        {
            int mid=ml+mr>>1;
            for(int i=nl;i<=nr;i++)
            {
                dijkstra(get(i,mid),nl,nr,ml,mr);
                for(int j=ql;j<=qr;j++) 
                    ans[a[j].p]=min(ans[a[j].p],dis[get(a[j].x1,a[j].y1)]+dis[get(a[j].x2,a[j].y2)]);
            }
            int l=ql-1,r=qr+1;
            for(int i=ql;i<=qr;i++)
                if(a[i].y1<mid&&a[i].y2<mid) b[++l]=a[i];
                else if(a[i].y1>mid&&a[i].y2>mid) b[--r]=a[i];
            for(int i=ql;i<=l;i++) a[i]=b[i];
            for(int i=qr;i>=r;i--) a[i]=b[i];
            solve(nl,nr,ml,mid-1,ql,l); solve(nl,nr,mid+1,mr,r,qr);
        }   
    }   
    void print(int x)
    {
        if(x==0)puts("0");
        char s[11];int i=0;
        while(x)s[++i]=x%10+'0',x/=10;
        while(i)putchar(s[i--]);puts("");
    }
    
    int main()
    {
        n=sc(),m=sc();
        for(int i=1;i<=n;i++)
            for(int j=1;j<m;j++)
            {
                int x=get(i,j),y=get(i,j+1),z=sc();
                insert(x,y,z);
            }
        for(int i=1;i<n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=get(i,j),y=get(i+1,j),z=sc();
                insert(x,y,z);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=get(i,j);
                px[x]=i,py[x]=j;
            }
        memset(ans,127,sizeof(ans));
        int w=0;Q=sc();
        for(int i=1;i<=Q;i++)
        {
            ++w;
            a[w].x1=sc(),a[w].y1=sc(),
            a[w].x2=sc(),a[w].y2=sc(),a[w].p=i;
            if(a[w].x1==a[w].x2&&a[w].y1==a[w].y2)ans[i]=0,w--;
        }
        solve(1,n,1,m,1,w);
        for(int i=1;i<=Q;i++)
            //print(ans[i]);
            printf("%d
    ",ans[i]);
        //cout<<endl;
        return 0;
    }
  • 相关阅读:
    hdu 1595(最短路变形好题)
    hdu 5253(最小生成树)
    hdu 2363(枚举+最短路好题)
    hdu 3440(差分约束好题)
    poj 3169&hdu3592(差分约束)
    hdu 3339(最短路+01背包)
    hdu 2145(迪杰斯特拉)
    CodeForces 581D Three Logos
    CodeForces 510E Fox And Dinner
    CodeForces 484D Kindergarten
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7230400.html
Copyright © 2020-2023  润新知