zoukankan      html  css  js  c++  java
  • Monkey King

    传送门

    我觉得这个题目翻译的特别好,真的。

    这个就是左偏树的模板题啦。每次找到这俩猴子所属的堆,然后如果不一样的话,就把两个堆里面最牛叉的两只猴子战斗力减成一半。我们用左偏树维护,取猴子的时候直接取顶端,然后我们把这个点的权值改成原来一半,重新合并就行啦。

    这题在做的时候莫名MLE……后来发现是自己在删除操作的时候忘记清空这个点的左右儿子信息了。一般左偏树的题是不需要清空,但是这道题里面需要修改之后合并回来,如果不清空可能会出很严重的问题。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define lowbit(x) x & (-x)
    
    using namespace std;
    typedef long long ll;
    const int M = 500005;
    const int INF = 1000000009;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    int n,m,root[M],lc[M],rc[M],val[M],dis[M],x,y;
    
    int merge(int x,int y)
    {
        if(!x || !y) return x | y;
        if(val[x] < val[y]) swap(x,y);
        rc[x] = merge(rc[x],y);
        root[rc[x]] = x;
        if(dis[lc[x]] < dis[rc[x]]) swap(lc[x],rc[x]);
        dis[x] = dis[rc[x]] + 1;
        return x;
    }
    
    int del(int x)
    {
        int l = lc[x],r = rc[x];
        root[lc[x]] = lc[x],root[rc[x]] = rc[x];
        lc[x] = rc[x] = dis[x] = 0;
        return merge(l,r);
    }
    
    int find(int x)
    {
        return (root[x] == x) ? x : root[x] = find(root[x]);
    }
    
    void clear()
    {
        memset(root,0,sizeof(root));
        memset(val,0,sizeof(val));
        memset(dis,0,sizeof(dis));
        memset(lc,0,sizeof(lc));
        memset(rc,0,sizeof(rc));
        dis[0] = -1;
    }
    
    int main()
    {
        while(scanf("%d",&n) != EOF)
        {
        clear();
        rep(i,1,n) val[i] = read(),root[i] = i;
        m = read();
        rep(i,1,m)
        {
            x = read(),y = read();
            int r1 = find(x),r2 = find(y);
            if(r1 == r2) printf("-1
    ");
            else
            {
            val[r1] >>= 1,val[r2] >>= 1;
            int f = del(r1),g = del(r2);
            int k1 = merge(f,r1),k2 = merge(g,r2);
            int k3 = merge(k1,k2);
            printf("%d
    ",val[k3]);
            }
        }
        }
        return 0;
    }
  • 相关阅读:
    安装VS 2015完成后,VS2012 打开报错
    ASP.NET MVC 项目中 一般处理程序ashx 获取Session
    windows平台 查看 dll 程序集 PublicKeyToken
    MySQL 表与字段编码格式报错
    Linux系统下安装MongoDB 指南
    ASP.NET 访问路径 错误提示 HTTP 错误 404.8 原来路径中包含bin目录被拒绝
    ASP.NET 大文件上传
    将类型(int,string,…)转换为 T 类型
    直接插入排序
    MySQL 优化之索引合并(index_merge)
  • 原文地址:https://www.cnblogs.com/captain1/p/9801223.html
Copyright © 2011-2022 走看看