2016vijos 6-1 松鼠聚会(LCA+卡空间)

求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
",lca(x,y));
    }
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8971405.html