zoukankan      html  css  js  c++  java
  • 2090. 「ZJOI2016」旅行者 分治,最短路

    2090. 「ZJOI2016」旅行者

    链接

    loj

    思路

    ((l,mid)(mid+1,r)).考虑跨过mid的贡献。

    假设选的中间那条线的点为gzy,贡献为(dis(x,gzy)+dis(gzy,y))

    那就计算n遍最短路,一次分治为(n^2mlog{nm})

    设S=n*m.矩阵的长度是不定的,每次取最长的边进行分治是最好的,n最坏为(sqrt{n})

    (f(n)=2*f(frac{n}{2})+Ssqrt{S}logS。所以总的复杂度就是)(Ssqrt{S}logS)

    都在同侧的也需要跨一跨
    代码

    #include <bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int _=1e5+7,INF=0x3f3f3f3f;
    int read() {
        int x=0,f=1;char s=getchar();
        for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
        for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
        return x*f;
    }
    int n,m,q,ans[_],vis[_];
    struct node {
        int x,y,X,Y,u,v,id;
    }Q[_],tmp[_];
    bool cmp(node a,node b) {return a.id<b.id;}
    struct edge {int v,nxt,q;}e[_];
    int head[_],tot;
    void add(int u,int v,int q) {
        e[++tot].v=v;
        e[tot].q=q;
        e[tot].nxt=head[u];
        head[u]=tot;
    }
    int id(int x,int y) {return (x-1)*m+y;}
    struct T_T {
        int u,val;
        T_T(int a=0,int b=0) {u=a,val=b;}
        bool operator < (const T_T &b) const {return val>b.val;}
    };
    int dis[_];
    void dij(int S) {
        dis[S]=0;
        priority_queue<T_T> q;
        q.push(T_T(S,0));
        while(!q.empty()) {
            T_T u=q.top();q.pop();
            if(dis[u.u]!=u.val) continue;
            for(int i=head[u.u];i;i=e[i].nxt) {
                int v=e[i].v;
                if(vis[v]&&dis[v]>u.val+e[i].q) {
                    dis[v]=u.val+e[i].q;
                    q.push(T_T(v,dis[v]));
                }
            }
        }
    }
    void solve(int x,int y,int X,int Y,int l,int r) {
        if(l>r) return;
        if(x==X&&y==Y) {
            for(int i=l;i<=r;++i) ans[Q[i].id]=0;
            return;
        }
        if(Y-y>X-x) {
            int mid=(Y+y)>>1;
            FOR(i,x,X) {
                FOR(j,x,X) FOR(k,y,Y) dis[id(j,k)]=INF;
                dij(id(i,mid));
                FOR(j,l,r)
                    ans[Q[j].id]=min(dis[Q[j].u]+dis[Q[j].v],ans[Q[j].id]);
            }
            FOR(i,x,X) vis[id(i,mid)]=0;
            int p=l,q=r;
            FOR(i,l,r) {
                if(max(Q[i].y,Q[i].Y)<=mid) tmp[p++]=Q[i];
                if(min(Q[i].y,Q[i].Y)>mid) tmp[q--]=Q[i];
            }
            FOR(i,l,r) Q[i]=tmp[i];
            solve(x,y,X,mid,l,p-1);
            solve(x,mid+1,X,Y,q+1,r);
        } else {
            int mid=(X+x)>>1;
            FOR(i,y,Y) {
                FOR(j,x,X) FOR(k,y,Y) dis[id(j,k)]=INF;
                dij(id(mid,i));
                FOR(j,l,r)
                    ans[Q[j].id]=min(dis[Q[j].u]+dis[Q[j].v],ans[Q[j].id]);
            }
            FOR(i,y,Y) vis[id(mid,i)]=0;
            int p=l,q=r;
            FOR(i,l,r) {
                if(max(Q[i].x,Q[i].X)<=mid) tmp[p++]=Q[i];
                if(min(Q[i].x,Q[i].X)>mid) tmp[q--]=Q[i];
            }
            FOR(i,l,r) Q[i]=tmp[i];
            solve(x,y,mid,Y,l,p-1);
            solve(mid+1,y,X,Y,q+1,r);
        }
    }
    int main() {
        n=read(),m=read();
        FOR(i,1,n) FOR(j,1,m-1) {
            int val=read();
            add(id(i,j),id(i,j+1),val);
            add(id(i,j+1),id(i,j),val);
        }
        FOR(i,1,n-1) FOR(j,1,m) {
            int val=read();
            add(id(i,j),id(i+1,j),val);
            add(id(i+1,j),id(i,j),val);
        }
        FOR(i,1,n) FOR(j,1,m) vis[id(i,j)]=1;
        q=read();
        FOR(i,1,q) {
            Q[i].x=read(),Q[i].y=read(),
            Q[i].u=id(Q[i].x,Q[i].y);
            Q[i].X=read(),Q[i].Y=read(),
            Q[i].v=id(Q[i].X,Q[i].Y);
            Q[i].id=i,ans[i]=INF;
        }
        solve(1,1,n,m,1,q);
        FOR(i,1,q) printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    Redis3.2集群部署安装
    熟悉SQL Server 数据类型
    泛型的参数简介和参数约束
    流(Stream)与文件流(FileStream)
    C#提取双引号中的字符串
    数组,一维数组,二维数组,交错数组
    结构,枚举
    C#中唯一的三元运算符
    位运算
    异常处理语句
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/11379880.html
Copyright © 2011-2022 走看看