• [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
    ");
                else printf("%d
    ",b[query(rt[f],v,1,n)]);
            }
        }
        return 0;
    }
  • 相关阅读:
    附上我的Github源码
    Java Automic包下的AtomicInteger
    思维题:四个小伙伴过桥问题
    TCP的三次握手过程?为什么会采用三次握手,若采用二次握手可以吗
    输入www.baidu.com会发生什么
    外网IP和内网IP区别
    Queue接口分析:add和offer区别,remove和poll方法到底啥区别
    手工创建一个线程池
    volatile关键字
    牛客网 买手串
  • 原文地址:https://www.cnblogs.com/acmsong/p/7505327.html
Copyright © 2020-2023  润新知