zoukankan      html  css  js  c++  java
  • 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);
    }
            
  • 相关阅读:
    vue使用elementui合并table
    使用layui框架导出table表为excel
    vue使用elementui框架,导出table表格为excel格式
    前台传数据给后台的几种方式
    uni.app图片同比例缩放
    我的博客
    【C语言】取16进制的每一位
    SharePoint Solution 是如何部署的呢 ???
    无效的数据被用来用作更新列表项 Invalid data has been used to update the list item. The field you are trying to update may be read only.
    SharePoint 判断用户在文件夹上是否有权限的方法
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10609328.html
Copyright © 2011-2022 走看看