zoukankan      html  css  js  c++  java
  • [HNOI2012]永无乡 SBT+启发式合并

    题目描述
    题目

    我也不知道启发式合并到底是什么东西
    好吧,启发式合并就是把小的集合往大的集合合并,学并查集的时候不是有把小树根的父亲设为大树根的操作吗,这大概就是启发式合并的一个典例

    对于这道题,我的做法是把小SBT的所有结点从小到大全部加入到大SBT中(本来打了个Treap,懒得旋转了,就改成了SBT,还好没有极限数据卡我),大概把并查集的操作省略了

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=100010;
    int n, q, w[N], m;
    
    struct node
    {
        node* ch[2];
        int v, id, s, r;
        node(int id, int v):id(id), v(v) {ch[0]=ch[1]=NULL; s=1; r=rand();}
        void maintain()
        {
            s=1;
            if(ch[0] != NULL) s+=ch[0]->s;
            if(ch[1] != NULL) s+=ch[1]->s;
        }
    };
    node* rt[N];
    //rt[i]记的是编号为i的结点所在SBT的根
    
    void ins(node* &o, int x, int v)
    {
        if(o == NULL) {o=new node(x, v); return ;}
        int d=(v > o->v); ins(o->ch[d], x, v);
        o->maintain();
    }
    
    void dfs(node* &o, node* &k)
    {
        if(k == NULL) return ;
        dfs(o, k->ch[0]);
        ins(o, k->id, k->v);
        dfs(o, k->ch[1]);
        delete k;
    }
    
    void merge(int a, int b)
    {
        if(rt[a] == NULL || rt[b] == NULL) return;
        if(rt[a]->s < rt[b]->s) swap(a, b);
        dfs(rt[a], rt[b]);
        rt[b]=rt[a];
    }
    
    int find(node* o, int k)
    {
        if(o == NULL || k <= 0 || k > o->s) return -1;
        int ss=(o->ch[0] == NULL ? 0 : o->ch[0]->s);
        if(k == ss+1) return o->id;
        if(k <= ss) return find(o->ch[0], k);
        return find(o->ch[1], k-ss-1);
    }
    
    int read(){
        int out=0;char c=getchar();while(c < '0' || c > '9') c=getchar();
        while(c >= '0' && c <= '9') out=(out<<1)+(out<<3)+c-'0',c=getchar();return out;
    }
    
    void solve()
    {
        n=read(), m=read();int u, v;
        for(int i=1; i <= n; i++) w[i]=read(), ins(rt[i], i, w[i]);
        for(int i=1; i <= m; i++) {u=read(), v=read(); merge(u, v);}
        q=read();
        for(int i=1; i <= q; i++) 
        {
            char c=getchar();
            while(c != 'B' && c != 'Q') c=getchar();
            if(c == 'B') 
            {
                u=read(), v=read();
                if(u > n || u < 1 || v > n || v <1) continue;
                if(rt[u] != rt[v]) merge(u, v);
            }
            else 
            {
                u=read(), v=read();
                if(u > n || u < 1) {printf("-1
    "); continue;}
                int ans=find(rt[u], v); printf("%d
    ",ans);
            }
        }
    }
    
    int main()
    {
        solve();
        return 0;
    }
    
  • 相关阅读:
    找到了2年前的一个微博小号
    Float Equal Problem
    有用的护肤品贴
    最近状态总结
    [Coursera]Machine Learning
    KMP算法(转载)
    [Leetcode] Median of Two Sorted Arrays
    [Algorithms(Princeton)] Week1
    [Algorithms(Princeton)] Week1
    [Leetcode] Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/zerolt/p/9260891.html
Copyright © 2011-2022 走看看