求LCA,N=1e6,原空间限制8MB
求LCA需要深度,需要跳跃一定距离的祖先,需要父节点
把一个整数压成3个char,f[]存父节点
g[],深度为奇数的点存往上跳576步能到的点,深度为偶数的点存深度
如果深度为奇数的点要求它的深度,求他父节点的深度+1
如果深度为偶数的点要求它往上跳576步的祖先,先往上跳一步,变成奇数深度
如何求往上跳576步的祖先?
1、往上跳6次1步,g就存的往上跳6步的祖先
2、往上跳6次6步,g就存的往上跳36步的祖先
3、往上跳4次36步,g就存的往上跳144步的祖先
4、往上跳4次144步,g就存的往上跳576步的祖先
还有,不能开iostream库,不然爆空间。。。
#include<cstdio> using namespace std; #define N 1000001 const int D=; struct node
{
char a,b,c;
}f[N],g[N]; inline int F(int i)
{
return ((f[i].a<<)+f[i].b<<)+f[i].c;
} inline int G(int i)
{
return ((g[i].a<<)+g[i].b<<)+g[i].c;
} inline int d(int i)
{
return G(i)<N ? G(i):G(F(i))+;
} void read(int &x)
{
x=; char c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<='') { x=x*+c-''; c=getchar(); }
} node turn(int x)
{
node y;
y.a=x>>;
y.b=(x>>)&;
y.c=x&;
return y;
} int lca(int x,int y)
{
int u;
if(d(x)<d(y)) u=x,x=y,y=u;
int dis=d(x)-d(y);
while(dis>=D)
{
if(G(x)<N) x=F(x),dis--;
else x=G(x)-N,dis-=D;
}
while(dis) x=F(x),dis--;
while(x!=y)
{
if(G(x)<N||G(x)==G(y)) x=F(x),y=F(y);
else x=G(x)-N,y=G(y)-N;
}
return x;
} int main()
{
freopen("squirrel.in","r",stdin);
freopen("squirrel.out","w",stdout);
int n,m;
read(n); read(m);
g[]=turn(N);
int x;
for(int i=;i<=n;++i)
{
read(x);
f[i]=turn(x),g[i]=turn(G(F(i))+);
}
for(int i=n;i;i--)
if(G(i)&)
{
x=i;
for(int j=;j<=;++j) x=F(x);
g[i]=turn(x+N);
}
for(int i=n;i;i--)
if(G(i)>N)
{
x=i;
for(int j=;j<=;++j) x=G(x)-N;
g[i]=turn(x+N);
}
for(int i=n;i;i--)
if(G(i)>N)
{
x=i;
for(int j=;j<=;++j) x=G(x)-N;
g[i]=turn(x+N);
}
for(int i=n;i;i--)
if(G(i)>N)
{
x=i;
for(int j=;j<=;++j) x=G(x)-N;
g[i]=turn(x+N);
}
int y;
while(m--)
{
read(x); read(y);
printf("%d\n",lca(x,y));
}
}