• P1852 [国家集训队]跳跳棋


             这什么神题啊…

             https://www.luogu.org/problemnew/show/P1852

             想了一个小时一点儿思路也没(头里只有爆搜) 看了题解才知道是树…这谁顶的住啊

             考虑中间点到两边距离相同的情况,此时显然已经不能往内部跳,只能向外部扩展,而可以证明的是,任意一种状态总能跳到这样一种状态(原理类似辗转相除),称为终态

             这样的话,如果两个状态的终态不同,那么它们一定不能相互转化

             如果二者终态相同,那么考虑不是终态的情况。显然只能有一种跳跃方式,因此每一个状态到终态的距离都是唯一的且可求的。我们把每一个状态看作点,所求就是始末态的lca

             这个思路有了以后,就很好做了。二分距离K考虑跳完之后是否在同一状态即可

             复杂度O(nlog^2n)

      

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define clr(a) memset(a,0,sizeof(a))
    inline 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) += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    struct node
    {
        int x,y,z;
        inline void sor() { if(x > y) swap(x,y); if(x > z) swap(x,z); if(y > z) swap(y,z); }
    }t1,t2,rt1,rt2,temp1,temp2;
    int find_root(node& b)
    {
        int stp = 0;
        b.sor();
        while(b.x + b.z != 2 * b.y)
        {
            int d1 = b.y - b.x,d2 = b.z - b.y;
            if(d1 < d2)
            {
                int tp = d2 / d1;
                if(d2 % d1 == 0) tp--;
                b.x += tp * d1;
                b.y += tp * d1;
                b.sor();
                stp += tp;
            }
            else 
            {
                int tp = d1 / d2;
                if(d1 % d2 == 0) tp--;
                b.y -= tp * d2;
                b.z -= tp * d2;
                b.sor();
                stp += tp;
            }
        }
        return stp;
    }
    bool same(node a,node b)
    { return a.x == b.x && a.y == b.y && a.z == b.z; }
    node get_pos(node b,int lim)
    {
         b.sor();
         while(lim)
        {
            int d1 = b.y - b.x,d2 = b.z - b.y;
            if(d1 < d2)
            {
                int tp = d2 / d1;
                if(d2 % d1 == 0) tp--;
                tp = min(tp,lim);
                b.x += tp * d1;
                b.y += tp * d1;
                b.sor();
                lim -= tp;
            }
            else 
            {
                int tp = d1 / d2;
                if(d1 % d2 == 0) tp--;
                tp = min(tp,lim);
                b.y -= tp * d2;
                b.z -= tp * d2;
                b.sor();
                lim -= tp;
            }
        }
        return b;
    }
    int st1,st2,ans;
    int main()
    {
        t1.x = read(),t1.y = read(),t1.z = read();
        t2.x = read(),t2.y = read(),t2.z = read();
        t1.sor();t2.sor();
        rt1 = t1,rt2 = t2; 
        st1 = find_root(rt1); st2 = find_root(rt2);
        if(!same(rt1,rt2)) { printf("NO"); return 0; }
        int st = abs(st1 -st2);
        if(st1 < st2) t2 = get_pos(t2,st);
        else t1 = get_pos(t1,st);
        int l = 0,r = min(st1,st2);
        while(l <= r)
        {
            int mid = l + r >> 1;
            temp1 = get_pos(t1,mid);
            temp2 = get_pos(t2,mid);
            if(same(temp1,temp2)) { ans = mid,r = mid - 1; }
            else l = mid + 1;
        }
        printf("YES
    %d",st + ans * 2);
    }
            
  • 相关阅读:
    Qt数据库集成应用封装
    Qt个人研究进展
    Qt仿win7自动顶部最大化左侧右侧半屏效果
    Qt编写QUI皮肤生成器
    java定时任务
    进程间通信(java)--队列
    单例设计模式-java
    Java RMI
    远程调用方式概述
    IO模型-java版
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10609328.html
Copyright © 2020-2023  润新知