LOJ6115 confluent block tree

This problem is very small space, that O (nlogn) lca tree algorithm is here not useful, and can be considered a tree block.

This question block tree is based on the depth, i.e. the depth of each press \ (\ sqrt n \) points a, and then jump up a piece, has at lca jump.

For this problem, there are several such practices:

Consider selecting a number of key points in the tree, each seeking lca to jump up at the critical point recently, and then a key point of a jump up, jump up at the same critical point. As for the selection of key points, you can do this:

From light to dark turn from every point of view, if the jump up 2S-1 nodes are not the key point, it is set to S-Class ancestor key points. From the first key thus key point number strictly less than n / S, while each keypoint to its father direction equal to S. And jump up from each point, a key point to the first number of steps required <2S.

Of course, the tree may be random \ (\ sqrt n \) key points, such complexity is desirable to \ (O (\ sqrt n) \) a.

Another approach gods psj provided is recorded at each point jump up \ (\ sqrt n \) times the ancestors, and then each time the query first two points before the jump to the same depth (depth can jump \ (O (\ sqrt n) \) queries get, jump when the dynamic maintenance), then multiply like lca that can jump up to jump up, but the step is \ (\ sqrt n \) , and finally in step by step jump lca Department. This approach is twice the space above practices have space to card a card too.

I write here is the first approach, the details can refer to the code:

#include<cstdio>
#include<bitset>
#include<algorithm>
using namespace std;
#define N 900007
#define M 5007
const int t=300;
int fa[N],a[M],top[M],dep[M],cnt;
bitset<N> tag;
void mark(int x)
{
    int v=fa[x],i;
    for(i=1;i<2*t&&!tag[v];i++)
        v=fa[v];
    if(i==2*t)
    {
        for(i=1;i<=t;i++)
            x=fa[x];
        a[++cnt]=x;
        tag[x]=1;
    }
}
int getpos(int x)
{
    int p=lower_bound(a+1,a+cnt+1,x)-a;
    return p;
}
int find(int x)
{
    while(!tag[x])x=fa[x];
    return x;
}
int getdep(int x,int y)
{
    int d=0;
    while(x!=y)
        d++,x=fa[x];
    return d;
}
int getkth(int x,int k)
{
    int i;
    for(i=1;i<=k;i++)
        x=fa[x];
    return x;
}
int main()
{
    int n,m,i,x,y;
    scanf("%d%d",&n,&m);
    for(i=2;i<=n;i++)
    {
        scanf("%d",&x);
        fa[i]=x;
    }
    tag[1]=1;
    a[++cnt]=1;
    for(i=2;i<=n;i++)
        mark(i);
    sort(a+1,a+cnt+1);
    dep[1]=1;
    for(i=2;i<=cnt;i++)
    {
        top[i]=getpos(find(fa[a[i]]));
        dep[i]=dep[top[i]]+1;
    }
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        int u=find(x),v=find(y);
        u=getpos(u),v=getpos(v);
        if(dep[v]>dep[u])swap(x,y),swap(u,v);
        while(dep[u]>dep[v])
        {
            x=a[u];
            u=top[u];
        }
        while(u!=v)
        {
            x=a[u],u=top[u];
            y=a[v],v=top[v];
        }
        int dx=getdep(x,a[u]),dy=getdep(y,a[v]);
        if(dy>dx)swap(x,y),swap(dx,dy);
        x=getkth(x,dx-dy);
        while(x!=y)
            x=fa[x],y=fa[y];
        printf("%d\n",x);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/lishuyu2003/p/11299594.html