大佬帮忙看一下

P3350 [ZJOI2016] 旅行者

system_has_collapsed @ 2018-03-06 13:06:02

大佬帮忙看一下

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int x = 0; bool f = 0; char ch;
    for (ch = getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=1;
    for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; if (f) x=-x;
    return x;
}
const int NN = 20010, MM = 100010, INF = 0x3f3f3f3f;
struct Q
{
    int x,len;
    friend bool operator < (Q xx,Q yy) { return xx.len > yy.len; }
};
priority_queue<Q> que;
int px[NN],py[NN],dis[NN],head[NN],ans[MM],n,m,tot,QQ,w;
bool vis[NN];
struct E
{
    int v,w,ne;
}e[NN<<2];
struct POI
{
    int xa,xb,ya,yb,num;
}p[MM],t[MM];
void Build(int xx,int yy,int zz)
{
    e[++tot].ne = head[xx], head[xx] = tot, e[tot].v = yy, e[tot].w = zz;
    e[++tot].ne = head[yy], head[yy] = tot, e[tot].v = xx, e[tot].w = zz;
}
int P(int xx,int yy) { return (xx-1)*m+yy; }
void DIJ(int xx,int nl,int nr,int ml,int mr)
{
    int t;
    for (int i=nl;i<=nr;++i)
        for (int j=ml;j<=mr;++j) t = P(i,j), dis[t] = INF, vis[t] = 0;
    dis[xx] = 0, que.push((Q){xx,0});
    while (!que.empty())
    {
        int now = que.top().x; que.pop();
        if (vis[now]) continue;
        vis[now] = 1;
        for (int i=head[now];i;i=e[i].ne)
        if (px[e[i].v]>=nl && px[e[i].v]<=nr && py[e[i].v]>=ml && py[e[i].v]<=mr)
        {
            if (dis[e[i].v] > dis[now] + e[i].w) dis[e[i].v] = dis[now] + e[i].w, que.push((Q){e[i].v,dis[e[i].v]});
        }
    }
}
void Solve(int nl,int nr,int ml,int mr,int ql,int qr)
{
    if (ql > qr) return;
    if (nr-nl > mr-ml)
    {
        int mid = (nl+nr) >> 1;
        for (int i=ml;i<=mr;++i)
        {
            DIJ(P(mid,i),nl,nr,ml,mr);
            for (int j=ql;j<=qr;++j) ans[p[j].num] = min(ans[p[j].num],dis[P(p[j].xa,p[j].ya)]+dis[P(p[j].xb,p[j].yb)]);
        }
        int l = ql-1, r = qr+1;
        for (int i=ql;i<=qr;++i)
            if (p[i].xa<mid && p[i].xb<mid) t[++l] = p[i];
                else if (p[i].xa>mid && p[i].xb>mid) t[--r] = p[i];
        for (int i=ql;i<=l;++i) p[i] = t[i];
        for (int i=r;i<=qr;++i) p[i] = t[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)
        {
            DIJ(P(i,mid),nl,nr,ml,mr);
            for (int j=ql;j<=qr;++j) ans[p[j].num] = min(ans[p[j].num],dis[P(p[j].xa,p[j].ya)]+dis[P(p[j].xb,p[j].yb)]);
        }
        int l = ql-1, r = qr+1;
        for (int i=ql;i<=qr;++i)
            if (p[i].ya<mid && p[i].yb<mid) t[++l] = p[i];
                else if (p[i].ya>mid && p[i].yb>mid) t[--r] = p[i];
        for (int i=ql;i<=l;++i) p[i] = t[i];
        for (int i=r;i<=qr;++i) p[i] = t[i];
        Solve(nl,nr,ml,mid-1,ql,l), Solve(nl,nr,mid+1,mr,r,qr);
    }
}
int main()
{
    n = read(), m = read();
    int x,y,z;
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j) x = P(i,j), px[x] = i, py[x] = j;
    for (int i=1;i<=n;++i)
        for (int j=1;j<m;++j)
        {
            x = P(i,j), y = P(i,j+1), z = read();
            Build(x,y,z);
        }
    for (int i=1;i<n;++i)
        for (int j=1;j<=m;++j)
        {
            x = P(i,j), y = P(i+1,j), z = read();
            Build(x,y,z);
        }
    QQ = read();
    for (int i=1;i <= QQ;++i)
    {
        ++w;
        p[w].xa = read(), p[w].ya = read(), p[w].xb = read(), p[w].yb = read();
        if (p[w].xa==p[w].xb && p[w].ya==p[w].yb) --w, ans[i] = 0; else p[w].num = i, ans[i] = INF;
    }
    Solve(1,n,1,m,1,w);
    for (int i=1;i<=QQ;++i) printf("%d\n",ans[i]);
    return 0;
}

测了几次都是50分

绝望


|