fzoj 2119 祖先问题

Problem 2119 祖先问题

Accept: 18    Submit: 82
Time Limit: 3000 mSec    Memory Limit : 32768 KB

 Problem Description

有n个结点构成了多棵树,给出每个结点的父节点,若为-1则表示该结点无父节点。每个结点的父节点编号必须比该结点的编号小。给m个操作,有两种操作:1.重新设置某结点的父节点;2.求某结点的祖先个数。一个结点的祖先为其父节点及其父节点的祖先。

 Input

有多组数据输入。每组数据的第一行为两个整数n,m。(1<=n,m<=200000)。第二行输入n个数,从1到n分别表示编号为1到n的结点的父节点,若为-1则表示该结点无父节点。接下来输入m行,表示m个操作,每行输入有两种:三个数t,a,b(t=0,1<= a <=n,b为-1或小于a的正整数),将结点a的父节点设置为b,若b为-1则表示将a设为无父节点;或者两个数t,a(t=1,1<=a<=n),表示询问结点a的祖先个数。数据保证每个结点的父节点编号比该结点小。所有输入都为整数。

 Output

对于每个询问输出一行一个整数,表示该结点的祖先数。

 Sample Input

4 3 -1 1 2 3 1 4 0 4 1 1 4

 Sample Output

3 1

 Source

FOJ有奖月赛-2013年4月(校赛热身赛)
 
思路:lct里面的access操作是把 自己到根的边置为重边,这样我们就可以直接用lct搞了
         
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#include<ctime>
#include<bitset>
#define LL long long
#define INF 0x3f3f3f3f
#define maxn 200010
#define eps 1e-6
#define mod 1000000007
using namespace std;

struct LCT
{
    int w[maxn],ff;
    int ch[maxn][2],pre[maxn] ;
    void init()
    {
        memset(ch,0,sizeof(ch)) ;
        memset(w,0,sizeof(w)) ;
        w[0]=0;
    }
    void update(int x )
    {
        w[x]=1+w[ch[x][1]]+w[ch[x][0]];
    }
    bool isroot(int x )
    {
        if(ch[pre[x]][0] != x && ch[pre[x]][1] != x )
            return true ;
        return false;
    }
    void rotate(int x,int f)
    {
        int y = pre[x],z = pre[y];
        ch[y][!f] = ch[x][f];
        pre[ ch[x][f] ] = y;
        pre[x] = pre[y];
        if(ch[z][0] == y)ch[z][0] = x;
        else if(ch[z][1] == y)ch[z][1] = x;
        pre[y] = x;
        ch[x][f] = y;
        update(y);
    }
    void splay(int x)
    {
        while(!isroot(x))
        {
            if(isroot(pre[x]))rotate(x,ch[pre[x]][0] == x);
            else
            {
                int y = pre[x],z = pre[y];
                int f = (ch[z][0] == y);
                if(ch[y][f] == x)rotate(x,!f),rotate(x,f);
                else rotate(y,f),rotate(x,f);
            }
        }
        update(x);
    }
    void access(int u)
    {
        int f;
        for(f = 0 ; u ;u = pre[u])
        {
            splay(u);
            ch[u][1] = f ;
            update(u);
            f = u ;
        }
        ff=f;
    }
    void cut(int x,int y )
    {
        access(y) ;
    }
    int find(int x)
    {
       access(x) ;
       splay(x);
       return w[x]-1;
    }
}lct;
int fa[maxn] ;
int main()
{
    int i , n ,m ,k ;
    int T,j ;
    while(scanf("%d%d",&n,&m) != EOF)
    {
        lct.init();
        for( i = 1 ; i <= n ;i++)
        {
            scanf("%d",&k) ;
            if(k==-1)
                lct.pre[i]=0,fa[i]=0;
            else lct.pre[i]=k,fa[i]=k;
        }
        while(m--)
        {
            scanf("%d",&k) ;
            if(k==1)
            {
                scanf("%d",&j) ;
                printf("%d
",lct.find(j)) ;
            }
            else
            {
                scanf("%d%d",&i,&j) ;
                if(fa[i] != 0)
                  lct.cut(i,fa[i]) ;
                  lct.splay(i);
                if(j==-1)fa[i]=lct.pre[i]=0;
                else lct.pre[i]=j,fa[i]=j;
            }
        }
    }
    return 0 ;
}
View Code
原文地址:https://www.cnblogs.com/20120125llcai/p/4075067.html