标签:ons iostream names getc amp else 要求 stdin 它的
求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=576; struct node { char a,b,c; }f[N],g[N]; inline int F(int i) { return ((f[i].a<<7)+f[i].b<<7)+f[i].c; } inline int G(int i) { return ((g[i].a<<7)+g[i].b<<7)+g[i].c; } inline int d(int i) { return G(i)<N ? G(i):G(F(i))+1; } void read(int &x) { x=0; char c=getchar(); while(c<‘0‘||c>‘9‘) c=getchar(); while(c>=‘0‘&&c<=‘9‘) { x=x*10+c-‘0‘; c=getchar(); } } node turn(int x) { node y; y.a=x>>14; y.b=(x>>7)&127; y.c=x&127; 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[0]=turn(N); int x; for(int i=2;i<=n;++i) { read(x); f[i]=turn(x),g[i]=turn(G(F(i))+1); } for(int i=n;i;i--) if(G(i)&1) { x=i; for(int j=1;j<=6;++j) x=F(x); g[i]=turn(x+N); } for(int i=n;i;i--) if(G(i)>N) { x=i; for(int j=1;j<=6;++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=1;j<=4;++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=1;j<=4;++j) x=G(x)-N; g[i]=turn(x+N); } int y; while(m--) { read(x); read(y); printf("%d\n",lca(x,y)); } }
标签:ons iostream names getc amp else 要求 stdin 它的
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8971405.html