hdu 1512 Monkey King —— 左偏树

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1512

很简单的左偏树;

但突然对 rt 的关系感到混乱,改了半天才弄对;

注意是多组数据!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e5+5;
int n,m,s[maxn],rt[maxn],ls[maxn],rs[maxn],dis[maxn];
int find(int x){while(rt[x])x=rt[x]; return x;}
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(s[x]<s[y])swap(x,y);
    rs[x]=merge(rs[x],y);
    rt[rs[x]]=x;
    if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
    if(rs[x])dis[x]=dis[rs[x]]+1;
    else dis[x]=0;
//    rt[rs[x]]=rt[ls[x]]=x;
    return x;
}
void clr(int x){rt[x]=0; rs[x]=0; ls[x]=0;}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)scanf("%d",&s[i]),ls[i]=rs[i]=dis[i]=rt[i]=0;
        scanf("%d",&m);
        for(int i=1,x,y,u,v,t1,t2;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            u=find(x); v=find(y);
            if(u==v){printf("-1\n"); continue;}
            rt[ls[u]]=0; rt[rs[u]]=0; rt[ls[v]]=0; rt[rs[v]]=0; //!
            t1=merge(ls[u],rs[u]);
            t2=merge(ls[v],rs[v]);
            clr(u); clr(v);//!
            s[u]>>=1; s[v]>>=1;
            merge(u,t1); merge(v,t2);
            printf("%d\n",s[merge(find(u),find(v))]);//find()
        }
    }
    return 0;
}

还可以把 rt 当并查集用,因为并查集实际上也是树,似乎更简洁;

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e5+5;
int n,m,s[maxn],rt[maxn],ls[maxn],rs[maxn],dis[maxn];
int find(int x){return rt[x]==x?x:rt[x]=find(rt[x]);}
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(s[x]<s[y])swap(x,y);
    rs[x]=merge(rs[x],y);
    rt[rs[x]]=x;
    if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
    if(rs[x])dis[x]=dis[rs[x]]+1;
    else dis[x]=0;
//    rt[rs[x]]=rt[ls[x]]=x;
    return x;
}
int del(int x)
{
    int l=ls[x],r=rs[x];
    rt[l]=l; rt[r]=r;
    ls[x]=rs[x]=dis[x]=0;
    return merge(l,r);
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)scanf("%d",&s[i]),rt[i]=i,ls[i]=rs[i]=dis[i]=0;
        scanf("%d",&m);
        for(int i=1,x,y,u,v,t1,t2;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            u=find(x); v=find(y);
            if(u==v){printf("-1\n"); continue;}
            s[u]>>=1; t1=del(u),t1=merge(u,t1);
            s[v]>>=1; t2=del(v),t2=merge(v,t2);
            printf("%d\n",s[merge(t1,t2)]);//find()
        }
    }
    return 0;
}

 

posted @ 2018-09-06 17:39  Zinn  阅读(134)  评论(0编辑  收藏  举报