Monkey King
很裸的左偏树题目。直接应用就可以了。
/*
author : 中南大学 陈安
PROG : hdu 1512
data structure: 左偏树
操作:
采用最大左偏树,所以每群猴子中权值最大的一定在树根
1.查询每群猴子中权值最大的,采用并查集,否则容易爆栈
2.对于修改操作,可以分解为如下步骤:
a.删除树根,合并左右子树,
b.修改原树根的值,
c.合并树根与新的子树
*/
#include <cstdio>
#include <cstring>
#define maxn 100010
struct Tree{
int l ;
int r ;
int v ;
int d ;
}tree[maxn];
int p[maxn];
int n ;
inline void InitTree(Tree &a){
a.l = -1 ;
a.r = -1 ;
a.v = -1 ;
a.d = 0 ;
}
inline void read(){
int x ;
for(int i = 1 ; i <= n ; i ++){
InitTree(tree[i]) ;
scanf("%d" , &tree[i].v) ;
}
}
inline int Get_Max(int x){
return tree[x].v ;
}
inline void swap(int &x ,int &y){
int t = x ;
x = y ;
y = t ;
}
int Merge(int x , int y){
if(x == -1) return y ;
if(y == -1) return x ;
if(tree[y].v > tree[x].v)
swap(x , y) ;
tree[x].r = Merge(tree[x].r , y) ;
if(tree[x].r != -1){
if(tree[x].l == -1 || tree[ tree[x].r ].d > tree[ tree[x].l ].d){
swap(tree[x].l , tree[x].r) ;
}
}
if(tree[x].r == -1){
tree[x].d = 0 ;
}
else{
tree[x].d = tree[tree[x].r].d + 1 ;
}
if(tree[x].l != -1){
p[ tree[x].l ] = x ;
}
if(tree[x].r != -1){
p[tree[x].r] = x ;
}
p[x] = x ;
return x ;
}
int Del_Max(int x){
int root = x ;
int val = tree[x].v ;
root = Merge(tree[root].l , tree[root].r) ;
//初始化该节点的值
InitTree(tree[x]) ;
tree[x].v = val ;
return root ;
}
int Insert(int x , int y){
return Merge(x , y) ;
}
int find(int x){
if(p[x]==x)
return x ;
else
return (p[x] = find(p[x])) ;
}
void joint(int x , int y){
int rx = find(x) ;
int ry = find(y) ;
if(rx != ry)
p[rx] = ry ;
}
void solve(){
int op ;
int x ;
int y ;
int rx ;
int ry ;
scanf("%d" ,&op) ;
for(int i = 0 ; i < op ; i ++){
scanf("%d%d" , &x , &y) ;
rx = find(x) ;
ry = find(y) ;
if(rx == ry)
printf("-1\n") ;
else{
//首先将根节点删除,
int rr1 = Del_Max(rx) ;
int rr2 = Del_Max(ry) ;
//将根节点的值减半
tree[rx].v = tree[rx].v >>1 ;
tree[ry].v = tree[ry].v >>1 ;
//然后将之前删掉的节点重新插入到树中
rr1 = Insert(rr1 , rx) ;
rr1 = Insert(rr1 , ry) ;
//将两棵左偏树合并
rr1 = Merge(rr1 , rr2) ;
printf("%d\n" , Get_Max(rr1)) ;
}
}
}
void init(){
for(int i = 1 ; i <= n ; i ++){
p[i] = i ;
}
}
int main(){
while(scanf("%d" , &n) != EOF){
init() ;
read() ;
solve() ;
}
return 0 ;
}