Box
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2421 Accepted Submission(s): 737
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.
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.
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
利用splay伸展树+lct的部分操作实现
由于不能改变根,只留access操作即可。
方法:
1. 查询点v的根,直接access,然后找父亲
2.对于改变子树到别的结点下,记录每个子树的父亲, access(fa[u])这样u就和父亲分开了,
然后令u的父亲为空,这样就把u这个子树给拆下来了。
判断合法性,只需要判断v是的父亲是否是u即可。
合法就令u的父亲为v
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define maxn 200007
#define inf 1000000000
#define ll int
struct Node{
Node *fa,*ch[2];
bool root;
int id;
};
Node pool[maxn];
Node *nil,*tree[maxn];
int cnt = 0;
void init(){
cnt = 1;
nil = tree[0] = pool;
nil->ch[0] = nil->ch[1] = nil;
nil->root = true;
nil->fa = nil;
nil->id = 0;
}
Node *newnode(int id,Node *f){
pool[cnt].fa = f;
pool[cnt].ch[0]=pool[cnt].ch[1]=nil;
pool[cnt].id = id;
pool[cnt].root = true;
return &pool[cnt++];
}
//将结点x旋转至splay中父亲的位置******
void rotate(Node *x){
Node *f = x->fa, *ff = f->fa;
int t = (f->ch[1] == x);
if(f->root)
x->root = true, f->root = false;
else ff->ch[ff->ch[1] == f] = x;
x->fa = ff;
f->ch[t] = x->ch[t^1];
x->ch[t^1]->fa = f;
x->ch[t^1] = f;
f->fa = x;
}
//将结点x旋转至x所在splay的根位置******
void splay(Node *x){
Node *f, *ff;
while(!x->root ){
f = x->fa,ff = f->fa;
if(!f->root)
if((ff->ch[1]==f)&&(f->ch[1] == x)) rotate(f);
else rotate(x);
rotate(x);
}
}
//将x到树根的路径并成一条path******
Node *access(Node *x){
Node *y = nil;
while(x != nil){
splay(x);
x->ch[1]->root = true;
(x->ch[1] = y)->root = false;
y = x;
x = x->fa;
}
return y;
}
char word[30];
Node* findroot(Node*x){
if(x->ch[0] == nil)return x;
return findroot(x->ch[0]);
}
Node*fa[maxn];
int main(){
int n,q,u,v,tt=0;
Node*x;
while(scanf("%d",&n)!=EOF){
if(tt)puts("");
tt++;
init();
for(int i = 1;i <= n; i++){
tree[i] = newnode(i,nil);
}
for(int i = 1;i <= n; i++){
scanf("%d",&u);
tree[i]->fa = tree[u];
fa[i] = tree[u];
}
scanf("%d",&q);
while(q--){
scanf("%s",word);
if(word[0] == 'Q'){
scanf("%d",&u);
x = access(tree[u]);
x = findroot(x);
printf("%d\n",x->id);
splay(x);
}
else {
scanf("%d%d",&u,&v);
access(fa[u]);
splay(tree[u]);
tree[u]->fa = nil;
x = access(tree[v]);
if(findroot(x) == tree[u]){
splay(tree[u]);
tree[u]->fa = fa[u];
}
else {
tree[u]->fa = tree[v];
fa[u] = tree[v];
}
}
}
}
return 0;
}
/*
2
0 1
50
QUERY 1
QUERY 2
MOVE 2 0
MOVE 1 2
QUERY 1
*/