题意:在一个森林里住着N(N<=10000)只猴子。在一开始,他们是互不认识的。但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识

(认识具有传递性)的两只猴子之间。争斗时,两只猴子都会请出他认识的猴子里最强壮的一只(有可能是他自己)进行争斗。争斗后,这两只猴子就互相认识。

每个猴子有一个强壮值,但是被请出来的那两只猴子进行争斗后,他们的强壮值都会减半(例如10会减为5,5会减为2)。现给出每个猴子的初始强壮值,

给出M次争斗,如果争斗的两只猴子不认识,那么输出争斗后两只猴子的认识的猴子里最强壮的猴子的强壮值,否则输出 -1。

析:我们可以通过并查集来判断是不是同一群,然后由于要改值和合并,要有一个合适的数据结构来维护,很容易想到是用左偏树,不过好像Splay也行。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 100000 + 10;
const int mod = 1e6 + 10;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
}
int p[maxn];
int Find(int x){ return x == p[x] ? x : p[x] = Find(p[x]); }
struct Node{
int key, l, r, fa, d;
};
Node tr[maxn]; int iroot(int i){
if(i == -1) return i;
while(tr[i].fa != -1) i = tr[i].fa;
return i;
} int Merge(int rx, int ry){
if(rx == -1) return ry;
if(ry == -1) return rx;
if(tr[rx].key < tr[ry].key) swap(rx, ry);
int r = Merge(tr[rx].r, ry);
tr[rx].r = r; tr[r].fa = rx;
if(tr[r].d > tr[tr[rx].l].d) swap(tr[rx].r, tr[rx].l);
if(tr[rx].r == -1) tr[rx].d = 0;
else tr[rx].d = tr[tr[rx].r].d + 1;
return rx;
} int Insert(int i, int key, int root){
tr[i].key = key;
tr[i].l = tr[i].r = tr[i].fa = -1;
tr[i].d = 0;
return Merge(root, i);
} int del(int i){
if(i == -1) return -1;
int l = tr[i].l, r = tr[i].r, y = tr[i].fa;
tr[i].l = tr[i].r = tr[i].fa = -1;
int x;
tr[x = Merge(l, r)].fa = y;
if(y != -1 && tr[y].l == i) tr[y].l = x;
if(y != -1 && tr[y].r == i) tr[y].r = x;
for( ; y != -1; x = y, y = tr[y].fa){
if(tr[tr[y].l].d < tr[tr[y].r].d) swap(tr[y].l, tr[y].r);
if(tr[y].d == tr[tr[y].r].d + 1) break;
tr[y].d = tr[tr[y].r].d + 1;
}
if(x != -1) return iroot(x);
return iroot(y);
} Node top(int root){ return tr[root]; } int add(int i){
if(i == -1) return i;
if(tr[i].l == -1 && tr[i].r == -1 && tr[i].fa == -1){
tr[i].key /= 2;
return i;
}
int key = tr[i].key / 2;
int rt = del(i);
return Insert(i, key, rt);
} void init(){
for(int i = 1; i <= n; ++i){
p[i] = i;
scanf("%d", &tr[i].key);
tr[i].l = tr[i].r = tr[i].fa = -1;
tr[i].d = 0;
}
} int main(){
while(scanf("%d", &n) == 1){
init();
scanf("%d", &m);
while(m--){
int u, v;
scanf("%d %d", &u, &v);
int x = Find(u);
int y = Find(v);
if(x == y){ printf("-1\n"); continue; }
p[y] = x;
int rt = iroot(u);
int rt1 = iroot(v);
rt = add(rt); rt1 = add(rt1);
int t = Merge(rt, rt1);
printf("%d\n", tr[t].key);
}
}
return 0;
}

  

HDU 1512 Monkey King (左偏树+并查集)的更多相关文章

  1. hdu 1512 Monkey King 左偏树

    题目链接:HDU - 1512 Once in a forest, there lived N aggressive monkeys. At the beginning, they each does ...

  2. hdu 1512 Monkey King —— 左偏树

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1512 很简单的左偏树: 但突然对 rt 的关系感到混乱,改了半天才弄对: 注意是多组数据! #includ ...

  3. zoj 2334 Monkey King/左偏树+并查集

    原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1389 大致题意:N只相互不认识的猴子(每只猴子有一个战斗力值) 两只 ...

  4. HDU 1512 Monkey King ——左偏树

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

  5. hdu1512 Monkey King(左偏树 + 并查集)

    Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its o ...

  6. HDU 1512 Monkey King(左偏堆)

    爱争吵的猴子 ★★☆ 输入文件:monkeyk.in 输出文件:monkeyk.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] 在一个森林里,住着N只好斗的猴子.开始,他们各 ...

  7. 洛谷 - P1552 - 派遣 - 左偏树 - 并查集

    首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...

  8. 洛谷 - P3377 - 【模板】左偏树(可并堆) - 左偏树 - 并查集

    https://www.luogu.org/problemnew/show/P3377 左偏树+并查集 左偏树维护两个可合并的堆,并查集维护两个堆元素合并后可以找到正确的树根. 关键点在于删除一个堆的 ...

  9. HDU 1512 Monkey King(左偏树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1512 [题目大意] 现在有 一群互不认识的猴子,每个猴子有一个能力值,每次选择两个猴子,挑出他们所 ...

随机推荐

  1. Linux 设置mysql开机启动

    linux开启启动的程序一般放在/etc/rc.d/init.d/里面,/etc/init.d/是其软连接 mysql设为linux服务 cp /usr/local/mysql/support-fil ...

  2. scrapy架构解析

  3. GIT / SVN 提交代码时, 注释该怎么写

    大致可以分为 6 种 : 添加 修改 修复 --> 修正 优化 --> 改进 ;

  4. 高德地图API开发二三事(一)如何判断点是否在折线上及引申思考

    最近使用高德地图 JavaScript API 开发地图应用,提炼了不少心得,故写点博文,做个系列总结一下,希望能帮助到LBS开发同胞们. 项目客户端使用高德地图 JavaScript API,主要业 ...

  5. Hadoop实战-Flume之Source replicating(十四)

    a1.sources = r1 a1.sinks = k1 k2 a1.channels = c1 c2 # Describe/configure the source a1.sources.r1.t ...

  6. 51Nod XOR key —— 区间最大异或值 可持久化字典树

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1295 1295 XOR key  题目来源: HackerRa ...

  7. Appium——api常用函数

    appium常用函数介绍:   获取页面信息:   1. def get_current_activity(cls, driver): ''' 获取当前页面的activity :param drive ...

  8. IDEA:Application Server was not connected before run configuration stop, reason: Unable to ping 1099

    原文链接 : http://blog.csdn.net/x6582026/article/details/70807269 最近第一次玩IDEA时碰到tomcat启动问题:Application Se ...

  9. css3立体旋转菜单

    css3立体旋转菜单,css3,3D,立体旋转,立体菜单,菜单导航,css3立体旋转菜单是一款纯css3实现的三维立体旋转导航菜单. 源码下载页:http://www.huiyi8.com/sc/71 ...

  10. laravel基础课程---15、分页及验证码(lavarel分页效果如何实现)

    laravel基础课程---15.分页及验证码(lavarel分页效果如何实现) 一.总结 一句话总结: 数据库的paginate方法:$data=\DB::table("user" ...