【luogu P1456 Monkey King】 题解

题目链接:https://www.luogu.org/problemnew/show/P1456
左偏树并查集不加路径压缩吧...

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 10;
struct Left_Tree{
    int val, fa, son[2], dis;
}h[maxn<<2];
int n, m;
int Merge(int r1, int r2)
{
    if(r1 == 0 || r2 == 0) return r1 + r2;
    if(h[r1].val < h[r2].val) swap(r1, r2);
    h[r1].son[1] = Merge(h[r1].son[1], r2);
    h[h[r1].son[1]].fa = r1;
    if(h[h[r1].son[0]].dis < h[h[r1].son[1]].dis) swap(h[r1].son[1], h[r1].son[0]);
    if(h[r1].son[1] == 0) h[r1].dis = 0;
    else h[r1].dis = h[h[r1].son[1]].dis + 1;
    return r1;
}
int destory(int r1)
{
    int le = h[r1].son[0], ri = h[r1].son[1];
    h[le].fa = 0;h[ri].fa = 0;
    int res = Merge(le, ri);
    h[r1].son[0] = h[r1].son[1] = 0;
    return res;
}
int find(int x)
{
    while(h[x].fa)
    x = h[x].fa;
    return x;
}
int main()
{
    while(scanf("%d",&n) != EOF)
    {
        for(int i = 1; i <= n; i++)
        {
            h[i].val = h[i].fa = 0;
            h[i].son[0] = h[i].son[1] = h[i].dis = 0;
        }
        for(int i = 1; i <= n; i++)
        scanf("%d",&h[i].val);

        scanf("%d",&m);
        for(int i = 1; i <= m; i++)
        {
            int opt, x, y;
            scanf("%d%d",&x,&y);
            int t1 = find(x), t2 = find(y);
            if(t1 == t2)
            {
                printf("-1\n");
                continue;
            }
                h[t1].val /= 2; h[t2].val /= 2;
                int left = destory(t1);
                int right = destory(t2);
                left = Merge(left, t1);
                right = Merge(right, t2);
                left = Merge(left, right);
                printf("%d\n",h[left].val);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/MisakaAzusa/p/9425999.html

时间: 2024-10-03 23:13:37

【luogu P1456 Monkey King】 题解的相关文章

Luogu P1456 Monkey King

左偏树. 并查集维护每个元素所在左偏树的根.每次取出堆顶除二再 merge 回去.然后 merge 两个点所在的堆. #include<iostream> #include<cstdio> #define R register int using namespace std; namespace Luitaryi { inline int g() { R x=0,f=1; register char s; while(!isdigit(s=getchar())) f=s=='-'?

P1456 Monkey King

题目地址:P1456 Monkey King 一道挺模板的左偏树题 不会左偏树?看论文打模板,完了之后再回来吧 然后你发现看完论文打完模板之后就可以A掉这道题不用回来了 细节见代码 #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 6; int n, m, f[N], a[N], l[N], r[N], d[N]; //类并查集路径压缩 int get(int x) { if (x == f[x]) return

洛谷P1456 Monkey King

https://www.luogu.org/problemnew/show/1456 #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 struct node { int lc,rc; int key,dis; }e[N]; int fa[N]; void read(int &x) { x=0; char c=getchar(

数据结构(左偏树):HDU 1512 Monkey King

Monkey King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4714    Accepted Submission(s): 2032 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, they e

[HDU1512]:Monkey King

Monkey King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6274    Accepted Submission(s): 2678 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, they e

ZOJ 2334 HDU 1512 Monkey King

题意: 猴子们打架  认识的猴子不会打架  两只猴子打完以后就认识了  A认识B B认识C A也认识C  每次打架由两伙猴子进行  分别选出自己的最高战斗力  在战斗之后两只猴子战斗力减半  给出m次打架  输出打架后这一伙猴子里的最强战斗力 思路: 判断两只猴子是不是一伙的  用到并查集 快速找出一伙猴子中的最强战斗力用到堆  但打完架两伙猴子合并时堆需要nlogn复杂度  因此用左偏树代替堆 代码: #include<cstdio> #include<cstring> #inc

【HDU 1512】Monkey King

Monkey King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3423    Accepted Submission(s): 1479 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, they

zoj2334 Monkey King , 并查集,可并堆,左偏树

提交地址:点击打开链接 题意:  N(N<=10^5)只猴子,初始每只猴子为自己猴群的猴王,每只猴子有一个初始的力量值.这些猴子会有M次会面.每次两只猴子x,y会面,若x,y属于同一个猴群输出-1,否则将x,y所在猴群的猴王的力量值减半,然后合并这两个猴群.新猴群中力量值最高的为猴王.输出新猴王的力量值. 分析:涉及集合的查询,合并,取最值. 利用并查集和左偏树即可解决. #include <cstdio> #include <cstring> #include <io

hdu 5201 The Monkey King 母函数 泰勒展开

题意: 有n个苹果,m个人,要求分给第一个人最多,其他人随意,求有多少种分法.最后结果模1000000007. 限制: 1 <= n,m <= 100000 思路: 母函数,泰勒展开 枚举第一个人分到的苹果,设为u, 剩下的苹果为n-u个,分成m-1份,则有: 生成函数为: G(x)=(1+x+x^2+...+x^(u-1))^(m-1) => G(x)=((1-x^u)/(1-x))^(m-1) => G(x)=(1-x^u)^(m-1) / (1-x)^(m-1) =>