您的位置:首页 > 其它

ZOJ2334 HDU1512 Monkey King,左偏树

2011-09-27 20:01 302 查看
学习了左偏树,发现及其强大,尤其是插入可以达到O(logN)的时间复杂度,我主要参考的是这些文章点击打开链接,又学到东西了

/*******************************************************************************
# Author : Neo Fung
# Email : neosfung@gmail.com
# Last modified: 2011-09-27 19:39
# Filename: ZOJ2334 HDU1512 Monkey King.cpp
# Description : 左偏树
******************************************************************************/
// #include "stdafx.h"
// #define DEBUG

#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <memory.h>
#define MAX 100100

using namespace std;

struct NODE
{
int r,l,val,dis;
}mon[MAX];
int pre[MAX];//用于保存祖先节点,其实这里可以把祖先节点保存在NODE中
int n,m;

void init(void)
{
for(int i=0;i<=n;++i)
pre[i]=i;
memset(mon,'\0',sizeof(mon));
}
int inline find(int x)
{
return x==pre[x]?x:pre[x]=find(pre[x]); //找到x的祖先节点
}

int merge(int a,int b)  //合并两个左偏树
{
if(a==0) return b;
if(b==0) return a;
if(mon[a].val<mon[b].val)	//由于根节点的值比子孙节点的值大,而且这里是递归把右边的树和左边的树的右子树合并,所以要保证左边的树的根的值比右边的树的根的值大
swap(a,b);
mon[a].r=merge(mon[a].r,b);//把右边的树和左边的树的右子树合并

pre[mon[a].r]=a;

if( mon[mon[a].l].dis<mon[mon[a].r].dis)
swap(mon[a].l, mon[a].r);// 保证右边的树的距离不大于左边的树的距离
if(mon[a].r==0)
mon[a].dis=0;
else
mon[a].dis=mon[mon[a].r].dis+1;
return a;
}

int solve( int a, int b)
{
int x=find(a),y=find(b);
int temp;
if(x==y) return -1;
mon[x].val /=2;
temp=merge(mon[x].l,mon[x].r);
mon[x].l=mon[x].r=mon[x].dis=0;
int xroot=merge(temp,x);

mon[y].val /=2;
temp = merge(mon[y].l , mon[y].r);
mon[y].l=mon[y].r=mon[y].dis=0;
int yroot=merge(temp , y);

temp=merge(xroot,yroot);

pre[x]=pre[y]=pre[xroot]=pre[yroot]=pre[a]=pre[b]=temp;

return mon[temp].val;
}

int main(void)
{
#ifdef DEBUG
freopen("data.txt","r",stdin);
#endif
int a,b;

while(scanf("%d",&n)!=EOF)
{
init();
for(int i=1;i<=n;++i)
scanf("%d",&mon[i].val);
scanf("%d",&m);
for(int i=0;i<m;++i)
{
scanf("%d %d",&a,&b);
printf("%d\n",solve(a,b));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: