标签:树,LCA
题目描述
三向城是一个巨大的城市,之所以叫这个名字,是因为城市中遍布着数不尽的三岔路口。(来自取名力为0的出题人)
具体来说,城中有无穷多个路口,每个路口有唯一的一个正整数标号。除了1号路口外,每个路口都连出正好3条道路通向另外3个路口:编号为x(x>1)的路口连出3条道路通向编号为x*2,x*2+1和x/2(向下取整)的3个路口。1号路口只连出两条道路,分别连向2号和3号路口。
所有道路都是可以双向通行的,并且长度都为1。现在,有n个问题:从路口x到路口y的最短路长度是多少?
输入格式
第一行包含一个整数n,表示询问数量;
接下来n行,每行包含两个正整数x, y,表示询问从路口x到路口y的最短路长度。
输出格式
输出n行,每行包含一个整数,表示对每次询问的回答。如果对于某个询问不存在从x到y的路径,则输出-1。
样例输入
3
5 7
2 4
1 1
样例输出
4
1
0
样例解释
5号路口到7号路口的路径为:5->2->1->3->7,长度为4;
2号路口到4号路口的路径为:2->4,长度为1;
1号路口到本身的路径长度为0;
数据范围
对30%的数据,x,y≤20;
对60%的数据,x,y≤105,n≤10;
对100%的数据,x,y≤109,n≤104。
先吐槽下出题人yy题目的语言功底……
T1难度,用LCA思想直接做
Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) #define ll long long #define mem(x,num) memset(x,num,sizeof x) #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif using namespace std; inline ll read() { ll f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxx=31; int n,depx,depy,ans=0; ll x,y; int Deep(ll x) { rep(k,1,maxx) if((ll)(1<<k)>x)return k; } int main() { freopen("city.in","r",stdin); freopen("city.out","w",stdout); n=read(); rep(i,1,n){ ans=0; x=read(),y=read(); depx=Deep(x),depy=Deep(y); if(depx<depy){swap(x,y);swap(depx,depy);} dep(j,depx,depy+1){x/=2;ans++;}//cout<<ans<<"R\n";cout<<x<<' '<<depx<<endl;cout<<y<<' '<<depy<<endl; dep(j,depy,0){if(x==y)break;x/=2,y/=2;ans+=2;} printf("%d\n",ans); } return 0; }