BZOJ2733: [HNOI2012]永无乡

时间:2019-03-19
本文章向大家介绍BZOJ2733: [HNOI2012]永无乡,主要包括BZOJ2733: [HNOI2012]永无乡使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

BZOJ2733: [HNOI2012]永无乡


题目描述

传送门

题目分析

题目要求合并集合和查询某个集合中的第\(k\)大,发现线段树合并可以做。

又有一个非常好的性质,一个权值对应唯一的一个位置,所以在权值线段树上直接在相应权值打上标记,查询的时候直接查询到底,合并直接上线段树合并,就可以了。

是代码呢

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
#define mid ((l+r)>>1)
int f[MAXN],st[MAXN<<5],L[MAXN<<5],R[MAXN<<5],T[MAXN],n,m,fa[MAXN<<5],sz,a[MAXN],q;
char opt[2];
inline int read()
{
    int x=0,c=1;
    char ch=' ';
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
inline int find(int x) {return f[x]==x?f[x]:f[x]=find(f[x]);}
inline int query(int x,int k)
{
    if(st[x]<k) return -1;
    if(st[x]==k) return fa[x];
    if(st[L[x]]<k) return query(R[x],k-st[L[x]]);
    else return query(L[x],k);
}
inline int query(int x,int l,int r,int k)
{
    if(st[x]<k) return -1;
    if(l==r) return fa[x];
    if(st[L[x]]<k) return query(R[x],mid+1,r,k-st[L[x]]);
    else return query(L[x],l,mid,k);
}
inline void modify(int &u,int l,int r,int k,int x)
{
    if(!u) u=++sz;
    if(l==r){
        st[u]++;fa[u]=x;
        return;
    }
    if(mid>=k) modify(L[u],l,mid,k,x);
    else modify(R[u],mid+1,r,k,x);
    st[u]=st[L[u]]+st[R[u]];
//  if(!R[u]) fa[u]=fa[L[u]];else fa[u]=fa[R[u]];
}
inline void merge(int &u,int v)
{
    if(!u||!v){u+=v;return;}
    st[u]+=st[v];
    merge(L[u],L[v]);merge(R[u],R[v]);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++) a[i]=read(),f[i]=i;
    for(int i=1;i<=n;i++) modify(T[i],1,n,a[i],i);
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        int r1=find(x),r2=find(y);
        if(r1==r2) continue;
        f[r2]=r1;
        merge(T[r1],T[r2]);
    }
    q=read();
    while(q--){
        scanf("%s",opt);
        int x=read(),y=read();
        if(opt[0]=='B'){
            int r1=find(x),r2=find(y);
            if(r1==r2) continue;
            f[r2]=r1;
            merge(T[r1],T[r2]);
        } else {
            int d=find(x);
            printf("%d\n",query(T[d],1,n,y));
        }
    }
}