[bzoj 2733]启发式合并权值线段树

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2733

平衡树待学习。从一个博客学到了合并权值线段树的姿势:http://blog.csdn.net/werkeytom_ftd/article/details/51761651

#include<bits/stdc++.h>
using namespace std;

const int maxn=100010;

int read(){
    int x=0;
    char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}

char get(){
    char ch=getchar();
    while (ch!='Q'&&ch!='B') ch=getchar();
    return ch;
}

struct Node
{
    int val,lson,rson;
}node[maxn+maxn*20];
int fa[maxn];
int a[maxn];
int b[maxn];
int tot;
int n;

int findfa(int u)
{
    if (fa[u]==u) return u;
    else return fa[u]=findfa(fa[u]);
}

int rt[maxn];

void insert(int root,int k,int l,int r)
{
    node[root].val++;
    if (l==r) return;
    int mid=(l+r)/2;
    if (k<=mid)
    {
        if (!node[root].lson) node[root].lson=++tot;
        insert(node[root].lson,k,l,mid);
    }
    else
    {
        if (!node[root].rson) node[root].rson=++tot;
        insert(node[root].rson,k,mid+1,r);
    }
}

int merge(int rt1,int rt2,int l,int r)
{
    if (!rt2) return rt1;
    if (!rt1) return rt2;
    if (l==r)
    {
        node[rt1].val+=node[rt2].val;
        return rt1;
    }
    int mid=(l+r)/2;
    node[rt1].val+=node[rt2].val;
    node[rt1].lson=merge(node[rt1].lson,node[rt2].lson,l,mid);
    node[rt1].rson=merge(node[rt1].rson,node[rt2].rson,mid+1,r);
    return rt1;
}

int query(int root,int k,int l,int r)
{
    if (l==r) return l;
    int mid=(l+r)/2;
    if (node[node[root].lson].val>=k) return query(node[root].lson,k,l,mid);
    else return query(node[root].rson,k-node[node[root].lson].val,mid+1,r);
}

void addedge(int u,int v)
{
    int f1=findfa(u);
    int f2=findfa(v);
    if (f1!=f2)
    {
        fa[f2]=f1;
        rt[f1]=merge(rt[f1],rt[f2],1,n);
    }
}

int main()
{
//    freopen("in.txt","r",stdin);
    int m;
    n=read();
    m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=n;i++) b[a[i]]=i;
    for (int i=1;i<=n;i++) fa[i]=i;
    for (int i=1;i<=n;i++) rt[i]=++tot;
    for (int i=1;i<=n;i++) insert(rt[i],a[i],1,n);
    for (int i=0;i<m;i++)
    {
        int u,v;
        u=read();
        v=read();
        addedge(u,v);
    }
    int q;
    q=read();
    while (q--)
    {
        char s;
        int u,v;
        s=get();
        u=read();
        v=read();
        if (s=='B') addedge(u,v);
        else
        {
            int f=findfa(u);
            if (node[f].val<v) printf("-1\n");
            else printf("%d\n",b[query(rt[f],v,1,n)]);
        }
    }
    return 0;
}

 

posted @ 2017-09-11 15:47  ACMsong  阅读(179)  评论(0编辑  收藏  举报