zoukankan      html  css  js  c++  java
  • LCA题目选讲2

    [LightOJ 1128]Greatest Parent

    这道题我们直接按照给出的父亲节点信息直接处理出倍增用的数组,然后直接倍增解决问题即可

    [BZOJ 2144]跳跳棋

    我们发现一种状态的转移只有三种,中间元素向两边跳两种和两边元素,所以我们把中间元素向左跳做左儿子,向右跳做右儿子,两边向中间跳作为他的父亲节点。我们发现当中间点恰好是两边点的中点的时候它没有父亲节点,即为根节点。

    我们跳到两种状态的根节点,看是否能够转移。

    然后二分答案,求出LCA的高度最后得到解

    看代码理解更佳

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    int read() {
        int a = 0, x = 1;
        char ch = getchar();
        while (ch > '9' || ch < '0') {
            if (ch == '-')
                x = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9') {
            a = a * 10 + ch - '0';
            ch = getchar();
        }
        return a * x;
    }
    struct node {
        int a[4];
        friend bool operator!=(node a, node b) {
            for (int i = 1; i <= 3; i++)
                if (a.a[i] != b.a[i])
                    return true;
            return false;
        }
        friend bool operator==(node a, node b) { return !(a != b); }
        void print() { printf("%lld %lld %lld
    ", a[1], a[2], a[3]); }
    } A, B;
    const int inf = 1e18;
    node r1, r2;
    int temp = 0, dep1, dep2;
    node find(node S, int k) {
        int z1 = S.a[2] - S.a[1], z2 = S.a[3] - S.a[2], tmp;
        if (z1 > z2) {
            tmp = min((z1 - 1) / z2, k);
            z1 -= tmp * z2;
            temp += tmp;
            k -= tmp;
            S.a[2] -= tmp * z2, S.a[3] -= tmp * z2;
        } else if (z1 < z2) {
            tmp = min((z2 - 1) / z1, k);
            z2 -= tmp * z2;
            k -= tmp;
            temp += tmp;
            S.a[1] += tmp * z1, S.a[2] += tmp * z1;
        }
        if (z1 == z2)
            return S;
        if (k)
            return find(S, k);
        return S;
    }
    
    signed main() {
        for (int i = 1; i <= 3; i++) A.a[i] = read();
        for (int i = 1; i <= 3; i++) B.a[i] = read();
        sort(A.a + 1, A.a + 4);
        sort(B.a + 1, B.a + 4);
        r1 = find(A, inf);
        dep1 = temp, temp = 0;
        r2 = find(B, inf);
        dep2 = temp, temp = 0;
        if (r1 != r2) {
            printf("NO");
            return 0;
        }
        if (dep1 < dep2) {
            swap(dep1, dep2);
            swap(A, B);
        }
        A = find(A, dep1 - dep2);
        int l = 0, r = dep2, mid;
        while (l != r) {
            mid = l + r >> 1;
            if (find(A, mid) == find(B, mid))
                r = mid;
            else
                l = mid + 1;
        }
        printf("YES
    %lld", l * 2 + (dep1 - dep2));
        return 0;
    }
    
  • 相关阅读:
    tnsnames.ora和listener.ora文件中的几个概念转
    SAP权限概念与设置(转)
    SAP License:HANA在线日志被误删了怎么办?(转)
    SAP ERP to SAP Cloud Platform Integration via Webdispatcher
    DotSpatial 要素删除节点
    DotSpatial 节点编辑
    使新添加的.gitignore生效
    关于netcat(nc)开启监听有趣的发现
    Gluster FS故障修复
    Git去除SSL验证
  • 原文地址:https://www.cnblogs.com/nao-nao/p/13712369.html
Copyright © 2011-2022 走看看