hdoj 1512 (左偏树)
来源:互联网 发布:光年seo日志分析工具 编辑:程序博客网 时间:2024/05/29 19:46
#include<cstdio>//#define MAX 100001#define MAX 10//左偏树struct Node{ int key,dis;//key就是键值,dis是距离(一个节点到它的后代中,最近的外节点所经过的边数) Node *left,*right;//左偏树是一个特殊的二叉树//初始化,都是NULL Node(int _key,int _dis,Node *null):key(_key),dis(_dis) { left=right=null; }}*null=new Node(-0x7fffffff,-1,NULL);//定义一个null,给null赋值//交换左右子树inline void SWAP(Node *&a,Node *&b) {Node *t=a; a=b; b=t; }//合并Node* Merge(Node *a,Node *b){ //如果a的键值小于b的键值,把这两个树交换if(a->key<b->key) SWAP(a,b); //如果b是空直接返回a树if(b==null) return a;//这样就确定了a的键值大于b的键值,递归的合并。 a->right=Merge(a->right,b);//如果a的左子树的距离小于a的右子树的距离,交换左右子树 if(a->left->dis<a->right->dis)SWAP(a->left,a->right);//将a的距离进行修改,返回a a->dis=a->right->dis+1; return a;}//插入,inline void Insert(Node *&p,int x){ p=Merge(p,new Node(x,0,null));}//删除,inline int Delete(Node *&p){ int ret=p->key; Node* newroot=Merge(p->left,p->right); delete p; p=newroot; return ret;}int n;Node *root[MAX];int set[MAX];//查找根节点int Find(int x){ if(set[x]==x) return x; return set[x]=Find(set[x]);}//主函数void work(){ int m,a,b; for(int i=1;i<=n;i++) { root[i]=null; scanf("%d",&a); Insert(root[i],a); set[i]=i;//set应该是并查集 } //输入冲突scanf("%d",&m); while(m--) { scanf("%d%d",&a,&b); int v1=Find(a),v2=Find(b);//如果两个猴子认识的话 if(v1==v2)printf("-1\n");//如果两个猴子不认识 else { int t1=Delete(root[v1]),t2=Delete(root[v2]); root[v1]=Merge(root[v1],root[v2]); Insert(root[v1],t1>>1);Insert(root[v1],t2>>1); set[v2]=v1; printf("%d\n",root[v1]->key); } }}int main(){freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { work(); } return 0;}