hdu 2475 BOX (splay)

hdu 2475

Splay树是一种神奇的东西。。。

题意:

  有一些箱子,要么放在地上,要么放在某个箱子里面 。

  现在有两种操作:

    (1) MOVE x y: 把 x 号箱子放到 y 号箱子里面,操作不合法就忽略这一次操作 。

    (2) QUERY x :  查询 x 号箱子最外面的箱子是哪一个

解法:

  首先对所有的树进行一遍DFS,得到一个DFS序,可以把它看成是一个括号序列,开始访问某个节点是左括号,结束访问时是右括号 。这样这题就转换成用Splay树来维护这个序列 。

  对于MOVE操作:

    将 x 对应那一段序列切下来,并将其放到 y 对应左括号的右边 。

  对于QUERY操作:

    直接查询以 x 为根的子树的最小值 。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <queue>
  7 #include <set>
  8 #include <vector>
  9 #include <map>
 10 #define ll long long
 11 
 12 using namespace std;
 13 
 14 const int N=50007;
 15 
 16 //  前向星
 17 struct edge{
 18     int to,nex;
 19 }e[N];
 20 int cnt;
 21 int head[N];
 22 
 23 inline void addedge(int u,int v){
 24     e[cnt].to=v; 
 25     e[cnt].nex=head[u];
 26     head[u]=cnt++;
 27 }
 28 
 29 int id[N*2];   // DFS序
 30 int cou;
 31 
 32 int tot;
 33 struct tree{
 34     int key,fa,son[2];
 35 }t[N*2];
 36 int L[N],R[N];  // 第i个箱子所对应的左右括号在Splay树上的序号
 37 
 38 inline void pushup(int x){}
 39 inline void pushdown(int x){}
 40 
 41 inline void rotate(int x,int p){
 42     int y=t[x].fa;
 43     pushdown(y);
 44     pushdown(x);
 45 
 46     t[y].son[!p]=t[x].son[p];
 47     t[t[x].son[p]].fa=y;
 48     t[x].fa=t[y].fa;
 49     if (t[x].fa)
 50         t[t[x].fa].son[t[t[x].fa].son[1]==y]=x;
 51     t[x].son[p]=y;
 52     t[y].fa=x;
 53     pushup(y);
 54     pushup(x);
 55 }
 56 
 57 inline void Splay(int x,int to){
 58     while (t[x].fa!=to){
 59         if (t[t[x].fa].fa==to)
 60             rotate(x,t[t[x].fa].son[0]==x);
 61         else {
 62             int y=t[x].fa, z=t[y].fa;
 63             int p=(t[z].son[0]==y);
 64             if (t[y].son[p]==x) 
 65                 rotate(x,!p),rotate(x,p);
 66             else
 67                 rotate(y,p),rotate(x,p);
 68         }
 69     }
 70 }
 71 
 72 inline int newnode(int key,int fa){
 73     int x=tot++;
 74     t[x].key=key;
 75     t[x].fa=fa;
 76     t[x].son[0]=t[x].son[1]=0;
 77 
 78     if (key>0) L[key]=x;
 79     else R[-key]=x;
 80 
 81     return x;
 82 }
 83 
 84 inline int get_min(int x){
 85     while (t[x].son[0]!=0)
 86         x=t[x].son[0];
 87     return x;
 88 }
 89 
 90 inline int get_max(int x){
 91     while (t[x].son[1]!=0) 
 92         x=t[x].son[1];
 93     return x;
 94 }
 95 
 96 inline int bulid(int l,int r,int fa){
 97     if (l>r) return 0;
 98     int x,mid=(l+r)>>1;
 99     x=newnode(id[mid],fa);
100     t[x].son[0]=bulid(l,mid-1,x);
101     t[x].son[1]=bulid(mid+1,r,x);
102     pushup(x);
103     return x;
104 }
105 
106 inline void dfs(int u){    
107     id[cou++]=u;
108     for (int i=head[u];~i;i=e[i].nex)
109         dfs(e[i].to);
110     id[cou++]=-u;
111 }
112 
113 inline void init(){
114     memset(head,-1,sizeof(head));
115     cnt=0;
116     cou=0;
117     tot=1;
118 }
119 
120 inline int query(int a){
121     int x=L[a];
122     Splay(x,0);
123     x=get_min(x);
124     return t[x].key;
125 }
126 
127 inline void move(int a,int b){
128     if (a==b) return;
129 
130     int x=L[a],y=R[a];
131     Splay(x,0);
132     Splay(y,x);
133 
134     int xx=t[x].son[0],yy=t[y].son[1],z=0;
135     z=get_max(xx);
136 
137     t[x].son[0]=0; t[y].son[1]=0;
138     t[xx].fa=0; t[yy].fa=0;
139     if (z!=0) t[z].son[1]=yy;
140     t[yy].fa=z;
141 
142     if (b==0) return;
143 
144     if (query(b)==a){
145         t[x].son[0]=xx; t[y].son[1]=yy;
146         t[xx].fa=x; t[yy].fa=y;
147         t[z].son[1]=0;
148         return;
149     }
150 
151     int l=L[b],r;
152     Splay(l,0);
153     r=get_min(t[l].son[1]);
154     Splay(r,l);
155     t[r].son[0]=x;
156     t[x].fa=r;
157 }
158 
159 int main(){
160     int n,q;
161     int x,y;
162     char ch[10];
163     bool f=false;
164     while (scanf("%d",&n)!=EOF){
165         if (f) puts("");
166         else f=true;
167 
168         init();
169         
170         for (int i=1;i<=n;i++){
171             scanf("%d",&x);
172             addedge(x,i);
173         }
174 
175         dfs(0);
176         int k=0,st=1;
177         for (int i=1;i<=2*n;i++){
178             if (id[i]>0) k++;
179             else k--;
180             if (k==0) {
181                 bulid(st,i,0);
182                 st=i+1;
183             }
184         }
185 
186         scanf("%d",&q);
187         while (q--){
188             scanf("%s",ch);
189             if (ch[0]=='Q') {
190                 scanf("%d",&x);
191                 printf("%d\n",query(x));
192             }
193             else {
194                 scanf("%d %d",&x,&y);
195                 move(x,y);
196             }
197         }
198     }
199 
200     return 0;
201 }

 

 

转载于:https://www.cnblogs.com/without-ACM/p/5931373.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值