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搞了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 ; }