• 【洛谷 P3224】 [HNOI2012]永无乡(Splay,启发式合并)


    题目链接
    启发式合并就是暴力合并把小的合并到大的里,一个一个插进去。
    并查集维护连通性,同时保证并查集的根就是所在Splay的根,这样能省去很多操作。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    inline int read(){
        int s = 0, w = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
        while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
        return s * w;
    }
    const int MAXN = 100010;
    struct SplayTree{
        int ch[2], fa, val, size;
    }t[MAXN];
    int num, root, n, m, f[MAXN];
    int find(int x){
        return f[x] == x ? x : f[x] = find(f[x]);
    }
    void pushup(int u){
        t[u].size = t[t[u].ch[0]].size + t[t[u].ch[1]].size + 1;
    }
    void rotate(int x){
        int y = t[x].fa;
        int z = t[y].fa;
        int k = t[y].ch[1] == x;
        t[z].ch[t[z].ch[1] == y] = x;
        t[x].fa = z;
        t[y].ch[k] = t[x].ch[k ^ 1];
        t[t[x].ch[k ^ 1]].fa = y;
        t[x].ch[k ^ 1] = y;
        t[y].fa = x;
        pushup(y);
        pushup(x);
    }
    void Splay(int x, int goal){
        while(t[x].fa){
          int y = t[x].fa, z = t[y].fa;
          if(z)
       /**/ (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
            rotate(x);
        }
        if(goal == 0) root = x;
    }
    inline int findKth(int k){
        int u = root;
        while(1){
          if(t[t[u].ch[0]].size >= k) u = t[u].ch[0];
          else if(t[t[u].ch[0]].size == k - 1) return u;
          else k -= t[t[u].ch[0]].size + 1, u = t[u].ch[1];
        }
    }
    int next(int x, int mode){
        int u = t[x].ch[mode];
        while(t[u].ch[!mode]) u = t[u].ch[!mode];
        return u;
    }
    int a, b;
    char c;
    void insert(int x){
        int u = root, fa = 0;
        while(u) fa = u, u = t[u].ch[t[x].val > t[u].val];
        t[fa].ch[t[x].val > t[fa].val] = x;
        t[x].fa = fa;
        Splay(x, 1);
    }
    void merge(int u){
        if(t[u].ch[0]) merge(t[u].ch[0]); 
        if(t[u].ch[1]) merge(t[u].ch[1]);
        t[u].ch[0] = t[u].ch[1] = 0; insert(u);
    }
    int T;
    int main(){
        n = read(); m = read();
        for(int i = 1; i <= n; ++i)
           t[i].val = read(), t[i].size = 1, f[i] = i;
        for(int i = 1; i <= m; ++i){
           a = read(); b = read();
           int x = find(a), y = find(b);
           if(x == y) continue;
           if(t[x].size > t[y].size){
               f[y] = x;
               root = x; merge(y); Splay(x, 0);
           }
           else{
               f[x] = y;
               root = y; merge(x); Splay(y, 0);
           }
        }
        T = read();
        for(int i = 1; i <= T; ++i){
           c = getchar(); while(c != 'Q' && c != 'B') c = getchar();
           a = read(); b = read();
           if(c == 'B'){
             int x = find(a), y = find(b);
             if(x == y) continue;
             if(t[x].size > t[y].size){
                 f[y] = x;
                 root = x; merge(y); Splay(x, 0);
             }
             else{
                 f[x] = y;
                 root = y; merge(x); Splay(y, 0);
             }
           }
           else{
             root = find(a);
           	 if(t[root].size < b) printf("%d
    ", -1);
           	 else printf("%d
    ", findKth(b));
           }
        }
        return 0;
    }
    
    
  • 相关阅读:
    防盗链(三)nginx实现图片防盗链(referer指令)
    防盗链(二)nginx secure_link下载防盗链
    防盗链(一)资料整理
    如何实现 token 加密
    Socket编程(三)demo举例
    Socket编程-(二)tcp三次握手与四次挥手
    Spring的事务控制,注解和xml配置以及解释
    SpringAop的核心概念和使用,表达式匹配刨析,xml配置通知和环绕通知
    SpringAop的简介
    Spring整合JUnit测试单元
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10807516.html
Copyright © 2020-2023  润新知