Hdu 2475-Box LCT,动态树

Box

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2813    Accepted Submission(s): 821


Problem Description
There are N boxes on the ground, which are labeled by numbers from 1 to N. The boxes are magical, the size of each one can be enlarged or reduced arbitrarily.
Jack can perform the “MOVE x y” operation to the boxes: take out box x; if y = 0, put it on the ground; Otherwise, put it inside box y. All the boxes inside box x remain the same. It is possible that an operation is illegal, that is, if box y is contained (directly or indirectly) by box x, or if y is equal to x.
In the following picture, box 2 and 4 are directly inside box 6, box 3 is directly inside box 4, box 5 is directly inside box 1, box 1 and 6 are on the ground.

The picture below shows the state after Jack performs “MOVE 4 1”:

Then he performs “MOVE 3 0”, the state becomes:

During a sequence of MOVE operations, Jack wants to know the root box of a specified box. The root box of box x is defined as the most outside box which contains box x. In the last picture, the root box of box 5 is box 1, and box 3’s root box is itself.
 

 

Input
Input contains several test cases.
For each test case, the first line has an integer N (1 <= N <= 50000), representing the number of boxes.
Next line has N integers: a1, a2, a3, ... , aN (0 <= ai <= N), describing the initial state of the boxes. If ai is 0, box i is on the ground, it is not contained by any box; Otherwise, box i is directly inside box ai. It is guaranteed that the input state is always correct (No loop exists).
Next line has an integer M (1 <= M <= 100000), representing the number of MOVE operations and queries.
On the next M lines, each line contains a MOVE operation or a query:
1.  MOVE x y, 1 <= x <= N, 0 <= y <= N, which is described above. If an operation is illegal, just ignore it.
2.  QUERY x, 1 <= x <= N, output the root box of box x.
 

 

Output
For each query, output the result on a single line. Use a blank line to separate each test case.
 

 

Sample Input
2 0 1 5 QUERY 1 QUERY 2 MOVE 2 0 MOVE 1 2 QUERY 1 6 0 6 4 6 1 0 4 MOVE 4 1 QUERY 3 MOVE 1 4 QUERY 1
 

 

Sample Output
1 1 2 1 1
 

 

Source
 

 

Recommend
lcy
 
题解:
LCT关于子树的问题。
判断y是否在x的子树中特别。。。
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 50010
  4 struct node
  5 {
  6     int left,right;
  7 }tree[MAXN];
  8 int father[MAXN],rev[MAXN],Stack[MAXN],cc[MAXN];
  9 int read()
 10 {
 11     int s=0,fh=1;char ch=getchar();
 12     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 13     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 14     return s*fh;
 15 }
 16 int isroot(int x)
 17 {
 18     return tree[father[x]].left!=x&&tree[father[x]].right!=x;
 19 }
 20 void pushdown(int x)
 21 {
 22     int l=tree[x].left,r=tree[x].right;
 23     if(rev[x]!=0)
 24     {
 25         rev[x]^=1;rev[l]^=1;rev[r]^=1;
 26         swap(tree[x].left,tree[x].right);
 27     }
 28 }
 29 void rotate(int x)
 30 {
 31     int y=father[x],z=father[y];
 32     if(!isroot(y))
 33     {
 34         if(tree[z].left==y)tree[z].left=x;
 35         else tree[z].right=x;
 36     }
 37     if(tree[y].left==x)
 38     {
 39         father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
 40     }
 41     else
 42     {
 43         father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
 44     }
 45 }
 46 void splay(int x)
 47 {
 48     int top=0,y,z,i;Stack[++top]=x;
 49     for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
 50     for(i=top;i>=1;i--)pushdown(Stack[i]);
 51     while(!isroot(x))
 52     {
 53         y=father[x];z=father[y];
 54         if(!isroot(y))
 55         {
 56             if((tree[y].left==x)^(tree[z].left==y))rotate(x);
 57             else rotate(y);
 58         }
 59         rotate(x);
 60     }
 61 }
 62 void access(int x)
 63 {
 64     int last=0;
 65     while(x!=0)
 66     {
 67         splay(x);
 68         tree[x].right=last;
 69         last=x;x=father[x];
 70     }
 71 }
 72 void makeroot(int x)
 73 {
 74     access(x);splay(x);rev[x]^=1;
 75 }
 76 void link(int u,int v)
 77 {
 78     makeroot(u);/*access(u);*/father[u]=v;splay(u);//
 79 }
 80 void cut(int u,int v)
 81 {
 82     /*makeroot(u);*//*access(u);*/access(u);splay(u);father[tree[u].left]=0;tree[u].left=0;
 83 }
 84 int findroot(int x)
 85 {
 86     access(x);splay(x);
 87     while(tree[x].left!=0)x=tree[x].left;
 88     return x;
 89 }
 90 int Findroot(int u,int v)
 91 {
 92     /*access(v);splay(v);*/access(v);splay(u);
 93     while(tree[u].right!=0)u=tree[u].right;
 94     if(u==v)return 1;
 95     return 0;
 96 }
 97 int main()
 98 {
 99     int n,i,m,k,x,y,a,tt=0;
100     char fh[30];
101     while(scanf("%d",&n)!=EOF)
102     {
103         if(tt)puts("");
104         tt++;
105         for(i=1;i<=n;i++)
106         {
107             tree[i].left=tree[i].right=father[i]=rev[i]=cc[i]=0;
108         }
109         for(i=1;i<=n;i++)
110         {
111             a=read();
112             if(a!=0)
113             {
114                 link(i,a);
115                 //cc[i]=a;
116             }
117         }
118         m=read();
119         for(i=1;i<=m;i++)
120         {
121             scanf("\n%s",fh);
122             if(fh[0]=='Q')
123             {
124                 k=read();
125                 printf("%d\n",findroot(k));
126             }
127             else
128             {
129                 x=read();y=read();
130                 if(y==0)cut(x,y);
131                 else if(x!=y)
132                 {
133                     if(Findroot(x,y)==1)continue;
134                     cut(x,y);link(x,y);
135                     /*access(y);splay(x);
136                     int t=x;
137                     while(tree[t].right!=0)t=tree[t].right;
138                     if(t!=y){cut(x,y);link(x,y);}*/
139                 }
140                 /*if(x!=0&&y!=0)
141                 {
142                     if(Findroot(y,x)==1)continue;
143                 }
144                 if(cc[x]!=0)
145                 {
146                     cut(x,cc[x]);
147                     //access(x);access(cc[x]);splay(cc[x]);father[tree[cc[x]].left]=0;tree[cc[x]].left=0;splay(cc[x]);//father[x]=tree[cc[x]].left=0;
148                 }
149                 cc[x]=y;
150                 if(cc[x]!=0)
151                 {
152                     //link(x,cc[x]);
153                     access(x);father[x]=cc[x];//splay(x);
154                 }*/
155             }
156         }
157         //printf("\n");
158     }
159     return 0;
160 }
View Code

 

转载于:https://www.cnblogs.com/Var123/p/5294244.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值