zoukankan      html  css  js  c++  java
  • zoj 2334 Monkey King/左偏树+并查集

    原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1389

    大致题意:N只相互不认识的猴子(每只猴子有一个战斗力值)

    两只不认识的猴子之间发生冲突,两只猴子会分别请出它们认识的最强壮的

    猴子进行决斗。决斗之后这,两群猴子都相互认识了。

    决斗的那两只猴子战斗力减半。。。有m组询问

    输入a b表示猴子a和b发生了冲突,若a,b属于同一个集合输出-1

    否则输出决斗之后这群猴子(已合并)中最强的战斗力值。。。

    具体思路:用并查集判断是否属于同一集合,用左偏树维护一群猴子的战斗力值。

    加了垃圾回收,否则容易爆内存。。。

    具体如下:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<iostream>
      4 #include<algorithm>
      5 const int Max_N = 100050;
      6 struct UnionFind{
      7     int par[Max_N], rank[Max_N];
      8     inline void init(int n){
      9         for (int i = 1; i <= n; i++){
     10             par[i] = i;
     11             rank[i] = 0;
     12         }
     13     }
     14     inline int find(int x){
     15         while (x != par[x]){
     16             x = par[x] = par[par[x]];
     17         }
     18         return x;
     19     }
     20     inline void unite(int x, int y){
     21         x = find(x), y = find(y);
     22         if (x == y) return;
     23         if (rank[x] < rank[y]){
     24             par[x] = y;
     25         } else {
     26             par[y] = x;
     27             if (rank[x] == rank[y]) rank[x]++;
     28         }
     29     }
     30 };
     31 struct Node{
     32     int v, npl;
     33     Node *ch[2];
     34     inline void set(int _v = 0, int _npl = -1, Node *p = NULL){
     35         v = _v, npl = _npl;
     36         ch[0] = ch[1] = p;
     37     }
     38     inline void push_up(){
     39         npl = ch[1]->npl + 1;
     40     }
     41 };
     42 struct LeftistTree{
     43     int N, top;
     44     UnionFind rec;
     45     Node *tail, *null;
     46     Node stack[Max_N], *ptr[Max_N], *store[Max_N];
     47     void init(int n){
     48         tail = &stack[0];
     49         null = tail++;
     50         null->set();
     51         N = n, top = 0, rec.init(n);
     52     }
     53     inline Node *newNode(int v){
     54         Node *p = null;
     55         if (!top) p = tail++;
     56         else p = store[--top];
     57         p->set(v, 0, null);
     58         return p;
     59     }
     60     inline Node* Merge(Node* &x, Node* &y){
     61         if (x == null) return y;
     62         if (y == null) return x;
     63         if (y->v > x->v) std::swap(x, y);
     64         x->ch[1] = Merge(x->ch[1], y);
     65         if (x->ch[1]->npl > x->ch[0]->npl)
     66             std::swap(x->ch[0], x->ch[1]);
     67         x->push_up();
     68         return x;
     69     }
     70     inline int get_max(int i){
     71         return ptr[i]->v;
     72     }
     73     inline void insert(){
     74         int v;
     75         for (int i = 1; i <= N; i++){
     76             scanf("%d", &v);
     77             ptr[i] = newNode(v);
     78         }
     79     }
     80     inline void del(int i){
     81         int ret = get_max(i);
     82         Node *x = newNode(ret >> 1);
     83         store[top++] = ptr[i];
     84         ptr[i] = Merge(ptr[i]->ch[0], ptr[i]->ch[1]);
     85         ptr[i] = Merge(ptr[i], x);
     86     }
     87     inline void gogo(int a, int b){
     88         int ans = 0;
     89         a = rec.find(a), b = rec.find(b);
     90         if (a == b){
     91             printf("-1
    ");
     92             return;
     93         }
     94         rec.unite(a, b);
     95         del(a), del(b);
     96         if (rec.rank[a] > rec.rank[b]){
     97             ptr[a] = Merge(ptr[a], ptr[b]);
     98             ans = ptr[a]->v;
     99         } else {
    100             ptr[b] = Merge(ptr[a], ptr[b]);
    101             ans = ptr[b]->v;
    102         }
    103         printf("%d
    ", ans);
    104     }
    105 }lft;
    106 int main(){
    107 #ifdef LOCAL
    108     freopen("in.txt", "r", stdin);
    109     freopen("out.txt", "w+", stdout);
    110 #endif
    111     int n, m, a, b;
    112     while (~scanf("%d", &n)){
    113         lft.init(n), lft.insert();
    114         scanf("%d", &m);
    115         while (m--){
    116             scanf("%d %d", &a, &b);
    117             lft.gogo(a, b);
    118         }
    119     }
    120     return 0;
    121 }
    View Code
    By: GadyPu 博客地址:http://www.cnblogs.com/GadyPu/ 转载请说明
  • 相关阅读:
    关于Unity中Mecanim动画的重定向与动画混合
    php远程抓取网站图片并保存
    OpenResty最佳实践
    111
    安装Nginx+Lua+OpenResty开发环境配置全过程实例
    ecshop常用的一些变量
    php 常用的标签比较
    PHP 设计模式
    mysql导入sql脚本
    linux 解压压缩大全
  • 原文地址:https://www.cnblogs.com/GadyPu/p/4463978.html
Copyright © 2011-2022 走看看