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\n");
 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\n", 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 }

时间: 2024-10-23 11:46:36

zoj 2334 Monkey King/左偏树+并查集的相关文章

猴子大王Monkey King 左偏树+并查集维护

Description Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its own way and none of them knows each other. But monkeys can't avoid quarrelling, and it only happens between two monkeys who does not know e

模板 - 左偏树 + 并查集

这两个经常混在一起用的样子,封成同一个好了. #include<bits/stdc++.h> using namespace std; typedef long long ll; int solve(); int main() { #ifdef Yinku freopen("Yinku.in","r",stdin); #endif // Yinku solve(); } int n,m; const int MAXN=100005; int tot,v[

hdu 1512 Monkey King 左偏树

题目链接:HDU - 1512 Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its own way and none of them knows each other. But monkeys can't avoid quarrelling, and it only happens between two monkeys who does not kn

[BZOJ1455]罗马游戏-斜堆/左偏树-并查集(+数据生成器)

Problem 遗产 题目大意 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果i, j有一个人是死人,那么就忽略该命令. 2. Kill(i).把i所在的团里面得分最低的人杀死.如果i这个人已经死了,这条命令就忽略. 皇帝希望他每发布一条kill命令

[BZOJ 1455]罗马游戏(左偏树+并查集)

Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果i, j有一个人是死人,那么就忽略该命令. 2. Kill(i).把i所在的团里面得分最低的人杀死.如果i这个人已经死了,这条命令就忽略. 皇帝希望他每发布一条kill命令,下面的

【BZOJ 1455】 1455: 罗马游戏 (可并堆-左偏树+并查集)

1455: 罗马游戏 Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果i, j有一个人是死人,那么就忽略该命令. 2. Kill(i).把i所在的团里面得分最低的人杀死.如果i这个人已经死了,这条命令就忽略. 皇帝希望他每发布一

bzoj 1455: 罗马游戏 左偏树+并查集

1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 668  Solved: 247[Submit][Status] Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果

HDU 1512 Monkey King ——左偏树

[题目分析] 也是堆+并查集. 比起BZOJ 1455 来说,只是合并的方式麻烦了一点. WA了一天才看到是多组数据. 盲人OI (- ̄▽ ̄)- Best OI. 代码自带大常数,比启发式合并都慢 [代码] #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <

zoj 2334 Monkey King

Monkey King ZOJ - 2334 题目大意:有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害.如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛.现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值. /* 左偏树模板题,包括合并,删除操作 */ #include<iostream> #