BZOJ 3362: [Usaco2004 Feb]Navigation Nightmare 导航噩梦
Posted 北屿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3362: [Usaco2004 Feb]Navigation Nightmare 导航噩梦相关的知识,希望对你有一定的参考价值。
Description
给你每个点与相邻点的距离和方向,求两点间的曼哈顿距离. \(n \leqslant 4\times 10^4\) .
Sol
加权并查集.
像向量合成一样合并就可以了,找 \(f[x]\) 的时候需要先记录现在的父节点,然后更新他新的父节点.
Code
/************************************************************** Problem: 3362 User: BeiYu Language: C++ Result: Accepted Time:80 ms Memory:3712 kb ****************************************************************/ #include<cstdio> #include<algorithm> #include<iostream> using namespace std; typedef pair< int,int > pr; #define abs(x) ((x)<0 ? -(x) : (x) ) #define mpr make_pair #define debug(a) cout<<#a<<"="<<a<<" " const int N = 40005; int n,m,k; int f[N],ans[N];pr g[N]; struct Q{ int a,b,c,d; }q[N],qq[N]; inline int in(int x=0,char ch=getchar()){ while(ch>‘9‘ || ch<‘0‘) ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x ;} inline char read(char ch=getchar()){ while(ch>‘Z‘ || ch<‘A‘) ch=getchar();return ch; } pr operator + (const pr &a,const pr &b){ return mpr(a.first+b.first,a.second+b.second); } pr operator += (pr &a,const pr &b){ return a=a+b; } pr operator - (const pr &a,const pr &b){ return mpr(a.first-b.first,a.second-b.second); } pr operator -= (pr &a,const pr &b){ return a=a-b; } int cmp1(const Q &x,const Q &y){ return x.c<y.c; } int cmp2(const Q &x,const Q &y){ return x.d<y.d; } int find(int x){ if(f[x] == x) return x; int t=f[x];f[x]=find(f[x]); g[x]+=g[t];return f[x]; } void work(int u,int v,int w,char d){ int r1=find(u),r2=find(v); // debug(r1),debug(r2)<<endl; // cout<<u<<" "<<v<<" "<<w<<" "<<d<<endl; // cout<<"qwq"<<endl; if(r1!=r2) switch(d){ case ‘N‘:f[r1]=r2,g[r1]=g[v]+mpr(0,w)-g[u];break; case ‘W‘:f[r1]=r2,g[r1]=g[v]+mpr(-w,0)-g[u];break; case ‘S‘:f[r1]=r2,g[r1]=g[v]+mpr(0,-w)-g[u];break; default:f[r1]=r2,g[r1]=g[v]+mpr(w,0)-g[u];break; } // for(int i=1;i<=n;i++) cout<<find(i)<<":("<<g[i].first<<","<<g[i].second<<") ";cout<<endl; } int main(){ // freopen("in.in","r",stdin); n=in(),m=in(); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) qq[i].a=in(),qq[i].b=in(),qq[i].c=in(),qq[i].d=read(); k=in();for(int i=1;i<=k;i++) q[i].a=in(),q[i].b=in(),q[i].c=in(),q[i].d=i; sort(q+1,q+k+1,cmp1); // for(int i=1;i<=m;i++) work(qq[i].a,qq[i].b,qq[i].c,qq[i].d); // for(int i=1;i<=n;i++) cout<<find(i)<<" ("<<g[i].first<<","<<g[i].second<<")\n"; for(int i=1,j=1,u,v,r1,r2;i<=k;i++){ for(;j<=q[i].c && j<=n;++j) work(qq[j].a,qq[j].b,qq[j].c,qq[j].d); u=q[i].a,v=q[i].b,r1=find(u),r2=find(v); if(r1==r2){ // debug(u),debug(v),debug(g[u].first),debug(g[v].first),debug(g[u].second),debug(g[v].second)<<endl; ans[q[i].d]=abs(g[u].first-g[v].first)+abs(g[u].second-g[v].second); }else ans[q[i].d]=-1; } // for(int i=1;i<=n;i++) cout<<find(i)<<" ("<<g[i].first<<","<<g[i].second<<")\n"; for(int i=1;i<=k;i++) printf("%d\n",ans[i]); return 0; }
以上是关于BZOJ 3362: [Usaco2004 Feb]Navigation Nightmare 导航噩梦的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3362/3363/3364/3365[Usaco2004 Feb]树上问题杂烩 并查集/树形dp/LCA/树的点分治
BZOJ 3364: [Usaco2004 Feb]Distance Queries 距离咨询
bzoj3367[Usaco2004 Feb]The Big Game 球赛*
BZOJ 3365: [Usaco2004 Feb]Distance Statistics 路程统计