您的位置:首页 > 其它

hdu2475 Box

2015-12-06 10:31 417 查看


Box

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2690    Accepted Submission(s): 788


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

2008 Asia Regional Chengdu 

 

Recommend

lcy

 

DFS序+splay,重点在于DFS序将一棵子树转化为一个区间

咦?这道题splay好像很好写…2333

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 100010
#define INF 1000000000
using namespace std;
int flag=0,rt,tot,cnt,n,m;
int c[MAXN][2],fa[MAXN],a[MAXN],head[MAXN];
bool f[MAXN];
char s[10];
struct edge_type
{
int next,to;
}e[MAXN];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void add_edge(int u,int v)
{
e[++tot]=(edge_type){head[u],v};
head[u]=tot;
}
inline void build(int &k,int l,int r,int father)
{
if (l>r) return;
int mid=(l+r)>>1;
k=a[mid];c[k][0]=c[k][1]=0;fa[k]=father;
build(c[k][0],l,mid-1,k);build(c[k][1],mid+1,r,k);
}
inline void rotate(int x,int k)
{
int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;
c[z][c[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
}
inline void splay(int x,int k)
{
if (x!=k) while (fa[x]!=k) rotate(x,k);
}
inline void move(int x,int y)
{
if (x==y) return;
splay(x,0);splay(x+n,x);
for(int i=y;i;i=fa[i]) if (c[x+n][0]==i) return;
int a=c[x][0],b=c[x+n][1];
c[x][0]=c[x+n][1]=fa[a]=fa[b]=0;
if (a&&b)
{
while (c[b][0]) b=c[b][0];
c[b][0]=a;fa[a]=b;
}
if (!y) return;
splay(y,0);
int tmp;
for(tmp=c[y][1];c[tmp][0];tmp=c[tmp][0]);
splay(tmp,y);
c[tmp][0]=x;fa[x]=tmp;
}
inline int query(int x)
{
splay(x,0);
for(;c[x][0];x=c[x][0]);
return x;
}
inline void dfs(int x)
{
a[++cnt]=x;
for(int i=head[x];i;i=e[i].next) dfs(e[i].to);
a[++cnt]=x+n;
}
int main()
{
int x,y;
while (~scanf("%d",&n))
{
if (flag++) printf("\n");
rt=tot=0;
memset(head,0,sizeof(head));
memset(fa,0,sizeof(fa));
memset(c,0,sizeof(c));
memset(f,false,sizeof(f));
F(i,1,n)
{
x=read();
if (x) add_edge(x,i);
else f[i]=true;
}
F(i,1,n) if (f[i])
{
cnt=0;
dfs(i);
build(rt,1,cnt,0);
}
m=read();
F(i,1,m)
{
scanf("%s",s);
if (s[0]=='Q')
{
x=read();
printf("%d\n",query(x));
}
else
{
x=read();y=read();
move(x,y);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: