大水题: 竟然TMD 没有看到这个题, CCCCC
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =250005;
int rmq[N*2];
struct ST
{
int mm[N*2];
int anc[2*N][20];
void init(int n)
{
mm[0]=-1;
for(int i=1;i<=n;i++){
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
anc[i][0]=i;
}
for(int j=1;j<=mm[n];j++){
for(int i=1;i+(1<<j)-1<=n;i++){
anc[i][j]=rmq[anc[i][j-1]] < rmq[anc[i+(1<<(j-1))][j-1]]?anc[i][j-1]:anc[i+(1<<(j-1))][j-1];
}
}
}
int query(int a,int b)
{
if(a>b) swap(a,b);
int k=mm[b-a+1];
return rmq[anc[a][k]] <= rmq[anc[b-(1<<k)+1][k]]?anc[a][k]:anc[b-(1<<k)+1][k];
}
};
struct node
{
int v,next;
}edge[N*2];
int tot,head[N];
int dfns[N*2]; /// 欧拉序列,也就是dfs序, 长度为2*n-1, 下标从1 开始.
int pp[N]; /// pp[i] 表示在dfns 中第一次出现的位置
//int L[N],R[N]; /// 表示当前节点dfs序中管辖的区间看情况使用
int cnt;
int clo; /// 时钟标记 用于L,R
ST st;
void init()
{
tot=clo=cnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[++tot].v=v; edge[tot].next=head[u]; head[u]=tot;
}
void dfs(int u,int fa,int deep)
{
dfns[++cnt]=u; rmq[cnt]=deep; pp[u]=cnt;
// L[u]=++clo;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==fa) continue;
dfs(v,u,deep+1);
dfns[++cnt]=u;
rmq[cnt]=deep;
}
//R[u]=clo;
}
void LCA_init(int rt,int node_num)
{
cnt=0;
dfs(rt,rt,0);
st.init(2*node_num-1);
}
int LCA(int u,int v)
{
return dfns[st.query(pp[u],pp[v])];
}
struct yjt
{
ll d;
ll r;
}mp[505][505];
struct eee
{
int u,v;
int f;
ll w;
}Edge[N*4];
int tot1;
int f[N];
int n,m;
char s[5];
int dep[N];
void build(int x1,int y1,int x2,int y2,ll val)
{
int id1=(x1-1)*m+y1;
int id2=(x2-1)*m+y2;
Edge[++tot1].u=id1;
Edge[tot1].v=id2;
Edge[tot1].w=val;
Edge[tot1].f=0;
Edge[++tot1].u=id2;
Edge[tot1].v=id1;
Edge[tot1].w=val;
Edge[tot1].f=0;
}
bool cmp(eee a,eee b)
{
return a.w>b.w;
}
int getf(int x)
{
return f[x]==x?x:(f[x]=getf(f[x]));
}
int merge(int u,int v)
{
int t1=getf(u);
int t2=getf(v);
if(t1!=t2){
f[t2]=t1;
return 1;
}
return 0;
}
void zuidashengchengshu()
{
sort(Edge+1,Edge+tot1+1,cmp);
for(int i=0;i<=n*m+2;i++) f[i]=i;
int cnt=0;
for(int i=1;i<=tot1;i++){
int u=Edge[i].u;
int v=Edge[i].v;
if(merge(u,v)){
cnt++;
Edge[i].f=1;
if(cnt==n*m-1) break;
}
}
init();
for(int i=1;i<=tot1;i++){
if(Edge[i].f){
add(Edge[i].u,Edge[i].v);
add(Edge[i].v,Edge[i].u);
}
}
LCA_init(1,n*m);
}
int main()
{
int x1,y1,x2,y2;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%s %lld %s %lld",s,&mp[i][j].d,s,&mp[i][j].r);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==n){
if(j==m) continue;
build(i,j,i,j+1,mp[i][j].r);
}
else{
if(j==m){
build(i,j,i+1,j,mp[i][j].d);
}
else{
build(i,j,i+1,j,mp[i][j].d);
build(i,j,i,j+1,mp[i][j].r);
}
}
}
}
zuidashengchengshu();
for(int i=1;i<=2*(n*m)-1;i++){
dep[dfns[i]]=rmq[i];
}
int Q;
scanf("%d",&Q);
while(Q--)
{
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
int id1=(x1-1)*m+y1;
int id2=(x2-1)*m+y2;
int lca=LCA(id1,id2);
int Ans=dep[id1]-dep[lca]+dep[id2]-dep[lca];
printf("%d\n",Ans);
}
return 0;
}