zoukankan      html  css  js  c++  java
  • [ZJOI2016]旅行者

    题目描述

    小Y来到了一个新的城市旅行。她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n*m个路口 (i,j)(1<=i<=n,1<=j<=m)。

    她发现不同的道路路况不同,所以通过不同的路口需要不同的时间。通过调查发现,从路口(i,j)到路口(i,j+1)需要时间 r(i,j),从路口(i,j)到路口(i+1,j)需要时间c(i,j)。注意这里的道路是双向的。小Y有q个询问,她想知道从路口(x1,y1)到路口(x2,y2)最少需要花多少时间。

    题解

    网格图上多次询问最短路,肯定要离线分治。

    CDQ整体二分什么的好像都不太适用。

    考虑正在分治一个矩形,我们可以把长的一边切断。

    然后把询问分为两种:起点和终点都在一侧、起点终点分居两侧。

    分居两侧的情况在把本次分治结束后答案已经更新完了,就把它扔掉就好了。

    对于本次分治,我们可以对分治中线上所有点矩形内跑一次最短路,然后对所有询问更新答案。

    然后递归分治两边.

    然鹅并不会分析复杂度。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 1e8
    #define N 100009
    #define mm make_pair
    using namespace std;
    priority_queue<pair<int,int> >q; 
    int n,m,dis[N],tot,head[N],ans[N];
    bool vis[N];
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x; 
    }
    struct edge{int n,to,l;}e[N<<2];
    struct query{
        int xf,yf,xs,ys,id;
    }a[N],b[N];
    inline void add(int u,int v,int l){
        e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
        e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;
    }
    inline int calc(int i,int j){return (i-1)*m+j;}
    inline bool pd(int id,int xf,int xs,int yf,int ys){
        int x=(id-1)/m+1,y=(id-1)%m+1;
        if(x>=xf&&x<=xs&&y>=yf&&y<=ys)return 1;else return 0; 
    }
    inline void spfa(int s,int xf,int xs,int yf,int ys){
        int x=dis[s];
        for(int i=xf;i<=xs;++i)
          for(int j=yf;j<=ys;++j){
              dis[calc(i,j)]+=x;
              vis[calc(i,j)]=0;
          }
        q.push(mm(0,s));dis[s]=0;
        while(!q.empty()){
            int u=q.top().second;q.pop();
            if(vis[u])continue;vis[u]=1;
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(!pd(v,xf,xs,yf,ys))continue;
                if(dis[v]>dis[u]+e[i].l){
                    dis[v]=dis[u]+e[i].l;
                    q.push(mm(-dis[v],v));
                }
            }
        }
    }
    void solve(int xf,int xs,int yf,int ys,int l,int r){
        if(l>r)return;
        if(xf==xs&&yf==ys){
            for(int i=l;i<=r;++i)ans[a[i].id]=0;
            return;
        }
        for(int i=xf;i<=xs;++i)
          for(int j=yf;j<=ys;++j)
              dis[calc(i,j)]=inf;
        if(xs-xf>ys-yf){
            int mid=(xf+xs)>>1;
            for(int i=yf;i<=ys;++i){
               spfa(calc(mid,i),xf,xs,yf,ys);
               for(int j=l;j<=r;++j)ans[a[j].id]=min(ans[a[j].id],dis[calc(a[j].xf,a[j].yf)]+dis[calc(a[j].xs,a[j].ys)]);
            }
            int L=l,R=r;
            for(int i=l;i<=r;++i){
                if(a[i].xf<=mid&&a[i].xs<=mid)b[L++]=a[i];
                else if(a[i].xf>mid&&a[i].xs>mid)b[R--]=a[i];
            }
            for(int i=l;i<=r;++i)a[i]=b[i];
            solve(xf,mid,yf,ys,l,L-1);solve(mid+1,xs,yf,ys,R+1,r);
        }
        else{
            int mid=(yf+ys)>>1;
            for(int i=xf;i<=xs;++i){
                spfa(calc(i,mid),xf,xs,yf,ys);
                for(int j=l;j<=r;++j)ans[a[j].id]=min(ans[a[j].id],dis[calc(a[j].xf,a[j].yf)]+dis[calc(a[j].xs,a[j].ys)]);
            }
            int L=l,R=r;
            for(int i=l;i<=r;++i){
                if(a[i].yf<=mid&&a[i].ys<=mid)b[L++]=a[i];
                else if(a[i].yf>mid&&a[i].ys>mid)b[R--]=a[i];
            }
            for(int i=l;i<=r;++i)a[i]=b[i];
            solve(xf,xs,yf,mid,l,L-1);solve(xf,xs,mid+1,ys,R+1,r);
        }
    }
    int main(){
        n=rd();m=rd();int x;
        for(int i=1;i<=n;++i)
          for(int j=1;j<m;++j){
              x=rd();add(calc(i,j),calc(i,j+1),x);
          }
        for(int i=1;i<n;++i)
          for(int j=1;j<=m;++j){
              x=rd();add(calc(i,j),calc(i+1,j),x);
          }
        memset(ans,0x3f,sizeof(ans));
        int q=rd();
        for(int i=1;i<=q;++i){
            a[i].xf=rd();a[i].yf=rd();a[i].xs=rd();a[i].ys=rd();
            a[i].id=i;
        }
        solve(1,n,1,m,1,q);
        for(int i=1;i<=q;++i)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    UE4代码片断备份
    程序到CPU的路径
    ue4 staticMesh属性记录
    UE4网络同步属性笔记
    UE4 行为树资料
    [转]浅谈B2C的数据分析
    [转载]网站分析的最基本度量(8)——Engagement
    [转载]评测流量来源(Traffic Source)的策略
    [转载]网站分析的最基本度量(7)——Impression,Click和CTR
    [转载]为什么”Bounce Rate”应该成为一个关键度量
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10381617.html
Copyright © 2011-2022 走看看