zoukankan      html  css  js  c++  java
  • bzoj4456: [Zjoi2016]旅行者

    传送门

    题解传送门

    zjoi难得碰到一道会做的题,,然而听说卡spfa又卡常?

    bz上还算是蹭着时限过了。。

    大常数选手大概说的就是我吧。。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=2e5+7;
    #define For(i,a,b) for(int i=(a);i<=(b);i++)
    #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    typedef long long LL;
    using namespace std;
    int n,m,q,ans[N];
    
    template<typename T>void read(T &x)  {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int ecnt,fir[N],nxt[N<<1],to[N<<1],val[N];
    void add(int u,int v,int w) {
        nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
        nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
    }
    
    int get(int x,int y) { return (x-1)*m+y; }
    void get(int xx,int &x,int &y) { y=xx%m; if(!y) y=m; x=xx/m; if(xx%m) x++; }
    int in(int x,int y,int l,int r,int L,int R) { return x>=l&&x<=r&&y>=L&&y<=R;  }
    
    struct node {
        int x,y,xx,yy,id;
    }qs[N],lq[N],rq[N];
    
    int dis[N],vis[N];
    struct dj {
        int x,dis;
        dj(int x,int dis):x(x),dis(dis){}
        friend bool operator <(const dj&A,const dj&B) {
            return A.dis>B.dis;
        }
    };
    priority_queue<dj>que;
    
    void dijkstra(int s,int l,int r,int L,int R) {
        For(i,l,r) For(j,L,R) {
            int x=get(i,j);
            dis[x]=ans[0]; vis[x]=0;
        }
        dis[s]=0;
        while(!que.empty()) que.pop();
        que.push(dj(s,0));
        while(!que.empty()) {
            dj x=que.top();
            que.pop();
            if(vis[x.x]||x.dis!=dis[x.x]) continue;
            vis[x.x]=1;
            for(int i=fir[x.x];i;i=nxt[i]) if(!vis[to[i]]) {
                int xx,yy; get(to[i],xx,yy);
                if(in(xx,yy,l,r,L,R)) {
                    if(dis[to[i]]>dis[x.x]+val[i]) {
                        dis[to[i]]=dis[x.x]+val[i];
                        que.push(dj(to[i],dis[to[i]])); 
                    }
                }
            }
        } 
    }
    
    void solve(int l,int r,int L,int R,int ql,int qr) {
        if(l>r||L>R||ql>qr) return;
        if(r-l<=R-L) {
            int mid=((L+R)>>1),ll=0,rr=0;
            For(i,l,r) {
                dijkstra(get(i,mid),l,r,L,R);
                For(j,ql,qr) {
                    ans[qs[j].id]=min(ans[qs[j].id],dis[get(qs[j].x,qs[j].y)]+dis[get(qs[j].xx,qs[j].yy)]);
                    if(i==l) {
                        if(in(qs[j].x,qs[j].y,l,r,L,mid)&&in(qs[j].xx,qs[j].yy,l,r,L,mid)) lq[++ll]=qs[j];
                        else if(in(qs[j].x,qs[j].y,l,r,mid+1,R)&&in(qs[j].xx,qs[j].yy,l,r,mid+1,R)) rq[++rr]=qs[j];
                    }
                }
            }
            For(i,1,ll) qs[ql+i-1]=lq[i]; For(i,1,rr) qs[ql+ll+i-1]=rq[i];
            if(l==r||L==R) return;
            solve(l,r,L,mid,ql,ql+ll-1); solve(l,r,mid+1,R,ql+ll,ql+ll+rr-1);
        }
        else {
            int mid=((l+r)>>1),ll=0,rr=0;
            For(i,L,R) {
                dijkstra(get(mid,i),l,r,L,R);
                For(j,ql,qr) {
                    ans[qs[j].id]=min(ans[qs[j].id],dis[get(qs[j].x,qs[j].y)]+dis[get(qs[j].xx,qs[j].yy)]);
                    if(i==L) {
                        if(in(qs[j].x,qs[j].y,l,mid,L,R)&&in(qs[j].xx,qs[j].yy,l,mid,L,R)) lq[++ll]=qs[j];
                        else if(in(qs[j].x,qs[j].y,mid+1,r,L,R)&&in(qs[j].xx,qs[j].yy,mid+1,r,L,R)) rq[++rr]=qs[j];
                    }
                }
            }
            For(i,1,ll) qs[ql+i-1]=lq[i]; For(i,1,rr) qs[ql+ll+i-1]=rq[i];
            if(l==r||L==R) return;
            solve(l,mid,L,R,ql,ql+ll-1); solve(mid+1,r,L,R,ql+ll,ql+ll+rr-1);
        }
    }
    
    //#define DEBUG 
    int main() {
    #ifdef DEBUG
        freopen("4456.in","r",stdin);
        freopen("4456.out","w",stdout);
    #endif
        read(n); read(m);
        For(i,1,n) 
            For(j,1,m-1) {
                int w; read(w);
                add(get(i,j),get(i,j+1),w);
            }    
        For(i,1,n-1)
            For(j,1,m) {
                int w; read(w);
                add(get(i,j),get(i+1,j),w);
            }
        read(q);
        For(i,1,q) {
            read(qs[i].x); read(qs[i].y);
            read(qs[i].xx); read(qs[i].yy);
            qs[i].id=i;
        }
        memset(ans,127/3,sizeof(ans));
        solve(1,n,1,m,1,q);
        For(i,1,q) printf("%d
    ",ans[i]);
        return 0;
    }
    /*
    2 2
    2
    3
    6 4
    2
    1 1 2 2
    1 2 2 1
    */
    View Code
  • 相关阅读:
    如何快速生成数据文件(fsutil命令,使用CreateFile和SetEndOfFile API函数,fopen和fseek RTL函数)
    TestDisk 数据恢复 重建分区表恢复文件-恢复diskpart clean
    利用winIO3.0进行windows10 64bit端口读取
    一个字体,大小,颜色可定义的自绘静态框控件-XColorStatic 类(比较好看,一共19篇自绘文章)
    美国富人与穷人的四个决定性差别!(冒风险、交朋友、敬业、生活习惯好)
    WebRTC 音视频开发
    协程的理解
    线程、进程、协程和队列
    Confluent
    “Options模式”下各种类型的Options对象是如何绑定的?
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8552279.html
Copyright © 2011-2022 走看看