bzoj 2733: [HNOI2012]永无乡【并查集+权值线段树】

bzoj上数组开大会T……
本来想用set瞎搞的,想了想发现不行
总之就是并查集,每个点开一个动态开点的权值线段树,然后合并的时候把值并在根上,询问的时候找出在根的线段树里找出k小值,看看这个值属于哪个岛即可

#include<iostream>
#include<cstdio>
using namespace std;
const int N=100005;
int n,m,q,f[N],rt[N],tot,rl[N];
char c[5];
struct qwe
{
    int ls,rs,s;
}t[10000005];
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>'9'||p<'0')
    {
        if(p=='-')
            f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9')
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
int zhao(int x)
{
    return f[x]==x?x:f[x]=zhao(f[x]);
}
void ud(int ro)
{
    t[ro].s=t[t[ro].ls].s+t[t[ro].rs].s;
}
void update(int &ro,int l,int r,int p)
{
    if(!ro)
        ro=++tot;
    if(l==r)
    {
        t[ro].s=1;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid)
        update(t[ro].ls,l,mid,p);
    else
        update(t[ro].rs,mid+1,r,p);
    ud(ro);
}
void hb(int &ro,int la,int l,int r)
{
    if(!la)
        return;
    if(!ro)
    {
        ro=la;
        return;
    }
    if(l==r)
    {
        t[ro].s+=t[la].s;
        return ;
    }
    int mid=(l+r)>>1;
    hb(t[ro].ls,t[la].ls,l,mid);
    hb(t[ro].rs,t[la].rs,mid+1,r);
    ud(ro);
}
int ques(int ro,int l,int r,int k)
{
    if(l==r)
        return l;
    int mid=(l+r)>>1;
    if(t[ro].ls&&t[t[ro].ls].s>=k)
        return ques(t[ro].ls,l,mid,k);
    else
        return ques(t[ro].rs,mid+1,r,k-t[t[ro].ls].s);
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
        int x=read();
        rl[x]=i;
        update(rt[i],1,n,x);
    }
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read(),fx=zhao(x),fy=zhao(y);
        if(fx!=fy)
        {
            f[fy]=fx;
            hb(rt[fx],rt[fy],1,n);
        }
    }
    q=read();
    while(q--)
    {
        scanf("%s",c);
        int x=read(),y=read();
        if(c[0]=='B')
        {
            int fx=zhao(x),fy=zhao(y);
            if(fx!=fy)
            {
                f[fy]=fx;
                hb(rt[fx],rt[fy],1,n);
            }
        }
        else
        {
            int fx=zhao(x);
            if(t[rt[fx]].s<y)
                puts("-1");
            else
                printf("%d\n",rl[ques(rt[fx],1,n,y)]);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lokiii/p/9695115.html
今日推荐