ZOJ2334 HDU1512 Monkey King,左偏树

来源:互联网 发布:淘宝哪个玩具店好 编辑:程序博客网 时间:2024/05/01 17:20

学习了左偏树,发现及其强大,尤其是插入可以达到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 100100using 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;elsemon[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;}


原创粉丝点击