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\n",ans[i]);
return 0;
}
/*
2 2
2
3
6 4
2
1 1 2 2
1 2 2 1
*/