bzoj2733: [HNOI2012]永无乡

Posted AKCqhzdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2733: [HNOI2012]永无乡相关的知识,希望对你有一定的参考价值。

这题是真的智障,个个都说什么启发式合并,其实就是暴力把小的那棵splay拆掉重新插入,不过就是每次判断一下那棵树的节点数少拆那棵,这样就O(nlogn^2).....

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int fa[110000];
int findfa(int x)
{
    if(fa[x]==x)return x;
    fa[x]=findfa(fa[x]);return fa[x];
}

//------f f--------

struct node
{
    int x,f,c,son[2];
}tr[110000];
void update(int x)
{
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].c=tr[lc].c+tr[rc].c+1;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int R,r;
    
    R=f,r=tr[x].son[w];
    tr[R].son[1-w]=r;
    if(r!=0)tr[r].f=R;
    
    R=ff,r=x;
         if(tr[R].son[0]==f)tr[R].son[0]=r;
    else if(tr[R].son[1]==f)tr[R].son[1]=r;
    tr[r].f=R;
    
    R=x;r=f;
    tr[R].son[w]=r;
    tr[r].f=R;
    
    update(f);
    update(x);
}
void splay(int x,int rt)
{
    while(tr[x].f!=rt)
    {
        int f=tr[x].f,ff=tr[f].f;
        if(ff==rt)
        {
            if(tr[f].son[0]==x)rotate(x,1);
            else rotate(x,0);
        }
        else
        {
                 if(tr[ff].son[0]==f&&tr[f].son[0]==x){rotate(f,1);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[1]==x){rotate(f,0);rotate(x,0);}
            else if(tr[ff].son[0]==f&&tr[f].son[1]==x){rotate(x,0);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[0]==x){rotate(x,1);rotate(x,0);}
        }
    }
}

//-------splay i--------------

int findip(int x,int y)
{
    while(1)
    {
        if(tr[x].x<tr[y].x)
        {
            if(tr[y].son[0]==0)return y;
            y=tr[y].son[0];
        }
        else
        {
            if(tr[y].son[1]==0)return y;
            y=tr[y].son[1];
        }
    }
}
void ins(int x,int y)
{
    int f=findip(x,y);
    tr[x].f=f;
    if(tr[x].x<tr[f].x)tr[f].son[0]=x;
    else tr[f].son[1]=x;
    update(f);splay(f,0);
}
void dfs(int x,int y)
{    
    ins(x,y);
    if(tr[x].son[0]!=0)dfs(tr[x].son[0],y);
    if(tr[x].son[1]!=0)dfs(tr[x].son[1],y);
}

int findshuzi(int x,int k)
{
    while(x!=0)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(tr[lc].c>=k)x=lc;
        else if(tr[lc].c+1<k)k-=tr[lc].c+1, x=rc;
        else return x;
    }
    return -1;
}

//--------splay o-----------

int a[110000];
char ss[10];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);fa[i]=i;
        tr[i].x=a[i];tr[i].f=0;tr[i].c=1;
        tr[i].son[0]=tr[i].son[1]=0;
    }
    
    int x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        if(x==0||y==0)continue;
        int fx=findfa(x),fy=findfa(y);
        if(tr[fx].c>tr[fy].c)swap(fx,fy);
        if(fx!=fy)fa[fx]=fy, dfs(fx,fy), splay(fy,0);
    }
    
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s%d%d",ss+1,&x,&y);
        if(x==0||y==0)continue;
        if(ss[1]==B)
        {
            int fx=findfa(x),fy=findfa(y);
            if(tr[fx].c>tr[fy].c)swap(fx,fy);
            if(fx!=fy)fa[fx]=fy, dfs(fx,fy), splay(fy,0);
        }
        else printf("%d\n",findshuzi(fa[x],y));
    }
    return 0;
}

 

以上是关于bzoj2733: [HNOI2012]永无乡的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2733: [HNOI2012]永无乡 启发式合并

[BZOJ] 2733: [HNOI2012]永无乡 #线段树合并+并查集

Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并

bzoj 2733: [HNOI2012]永无乡

BZOJ2733: [HNOI2012]永无乡

[bzoj2733] [HNOI2012]永无乡