BZOJ 2733 [HNOI2012]永无乡 ——线段树 并查集

用并查集维护联通块。

用线段树的合并来合并联通块。

自己YY了一个写法。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 150005
 
 
int ls[maxn<<5],rs[maxn<<5],rt[maxn];
int fa[maxn],n,m,tot,sum[maxn<<5],q; char opt[11];
 
void modify(int o1,int &o2,int l,int r,int x,int f)
{
    o2=++tot;sum[o2]=sum[o1]+f;if(l==r)return;int mid=l+r>>1;
    if (x<=mid) rs[o2]=rs[o1],modify(ls[o1],ls[o2],l,mid,x,f);
    else ls[o2]=ls[o1],modify(rs[o1],rs[o2],mid+1,r,x,f);
}
 
int gf(int k)
{
    if (fa[k]==k) return k;
    else return fa[k]=gf(fa[k]);
}
 
int merge(int o1,int o2,int l,int r)
{
    if (!(o1*o2)) return o1+o2;
    int mid=l+r>>1;sum[o1]+=sum[o2];
    ls[o1]=merge(ls[o1],ls[o2],l,mid);
    rs[o1]=merge(rs[o1],rs[o2],mid+1,r);
    return o1;
}
 
int query(int o,int l,int r,int x)
{
    if (sum[o]<x) return -1;
    if (l==r) return l;
    int mid=l+r>>1;
    if (x<=sum[ls[o]]) return query(ls[o],l,mid,x);
    else return query(rs[o],mid+1,r,x-sum[ls[o]]);
}
 
void Debug(int o,int l,int r)
{
    if (!o) return ;
    printf(" %d %d == %d\n",l,r,sum[o]);
    if (l==r) return ;
    Debug(ls[o],l,l+r>>1);
    Debug(rs[o],(l+r>>1)+1,r);
}
 
int list[maxn];
 
int main()
{
    scanf("%d%d",&n,&m);
    F(i,1,n) fa[i]=i,rt[i]=0;
    F(i,1,n)
    {
        int x;
        scanf("%d",&x);
        modify(rt[i],rt[i],1,n,x,1);
        list[x]=i;
    }
    F(i,1,m)
    {
        int x,y,fx,fy; scanf("%d%d",&x,&y);
        fx=gf(x);fy=gf(y);
        if (fx==fy) continue;
        else
            fa[fy]=fx,rt[fx]=merge(rt[fx],rt[fy],1,n);
    }
    scanf("%d",&q);
    F(i,1,q)
    {
        int x,y,fx,fy,tmp;
        scanf("%s%d%d",opt,&x,&y);
        switch(opt[0])
        {
            case 'Q':
                fx=gf(x);
                tmp=query(rt[fx],1,n,y);
                printf("%d\n",tmp==-1?-1:list[query(rt[fx],1,n,y)]);
            break;
            case 'B':
                fx=gf(x);fy=gf(y);
                if (fx!=fy)
                {
                    fa[fy]=fx;
                    rt[fx]=merge(rt[fx],rt[fy],1,n);
                }
            break;
        }
    }
}

  

posted @ 2017-04-20 17:14  SfailSth  阅读(123)  评论(0编辑  收藏  举报