hdu 2475 Box splay, lct

来源:互联网 发布:房地产行业数据分析 编辑:程序博客网 时间:2024/05/05 08:42

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.
 

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
20 15QUERY 1QUERY 2MOVE 2 0MOVE 1 2QUERY 160 6 4 6 1 04MOVE 4 1QUERY 3MOVE 1 4QUERY 1
 

Sample Output
11211
 

Source
2008 Asia Regional Chengdu

利用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 intstruct 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;}/*20 150QUERY 1QUERY 2MOVE 2 0MOVE 1 2QUERY 1*/


0 0
原创粉丝点击