cogs526 愛爭吵的猴子

傳送門

左偏樹。
每次合併的時候取出堆頂,然後合併堆頂的左右兒子,最後將堆頂所代表的猴子的強壯值減半扔到左偏樹裏。
維護父親的時候用並查集實現。
實現的時候有些細節需要注意。

CODE:

#include<cstdio>
#include<iostream>
using namespace std;
struct node
{
    int num,dis,id;
    node *ch[2];
}pool[300005],*t[300005],*null;
int f[300005];
int n,m,x,y,tot;
inline node *getnew(int value,int id)
{
    node *now=pool+ ++tot;
    now->ch[0]=now->ch[1]=null;
    now->num=value,now->id=id;
    now->dis=0;
    return t[tot]=now;
}
inline int find(int n)
{
    if(f[n]!=n) f[n]=find(f[n]);
    return f[n];
}
node *merge(node *x,node *y)
{
    if(x==null) return y;
    if(y==null) return x;
    if(x->num<y->num||(x->num==y->num&&x->id>y->id)) swap(x,y);
    x->ch[1]=merge(x->ch[1],y);
    if(x->ch[0]->dis<x->ch[1]->dis) swap(x->ch[0],x->ch[1]);
    x->dis=x->ch[1]->dis+1;
    return x;
}
inline int Merge(int x,int y)
{
    node *t1=t[x],*t2=t[y];
    int num1=t1->num,num2=t2->num;
    t1=merge(t1->ch[0],t1->ch[1]);
    t2=merge(t2->ch[0],t2->ch[1]);
    if(t1!=null)
    {
        f[t1->id]=t1->id;
        if(t1->ch[0]!=null) f[t1->ch[0]->id]=t1->id;
        if(t1->ch[1]!=null) f[t1->ch[1]->id]=t1->id;
    }
    if(t2!=null)
    {
        f[t2->id]=t2->id;
        if(t2->ch[0]!=null) f[t2->ch[0]->id]=t2->id;
        if(t2->ch[1]!=null) f[t2->ch[1]->id]=t2->id;
    }
    t1=merge(t1,getnew(num1>>1,tot+1)),f[tot]=t1->id;
    t2=merge(t2,getnew(num2>>1,tot+1)),f[tot]=t2->id;
    node *root=merge(t1,t2);
    f[x]=f[y]=f[t1->id]=f[t2->id]=root->id;
    return t[find(t1->id)]->num;
}
int main()
{
    freopen("monkeyk.in","r",stdin);
    freopen("monkeyk.out","w",stdout);
    null=pool;
    null->ch[0]=null->ch[1]=null;
    null->dis=-1;
    while(scanf("%d",&n)!=EOF)
    {
        tot=0;
        for(int i=1;i<=n;i++)
          scanf("%d",&x),getnew(x,i);
        scanf("%d",&m);
        for(int i=1;i<=n+m;i++)
          f[i]=i;
        while(m--)
        {
            scanf("%d%d",&x,&y);
            x=find(x),y=find(y);
            if(x!=y) printf("%d\n",Merge(x,y));
            else printf("-1\n");
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章