题目描述

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。我们用跳跳棋来做一个简单的
游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋
子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只
允许跳过1颗棋子。

写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

输入

第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)
第二行包含三个整数,表示目标位置x y z。(互不相同)

输出

如果无解,输出一行NO。如果可以到达,第一行输出YES,第二行输出最少步数。

样例输入

1 2 3
0 3 5

样例输出

YES
2
【范围】
100% 绝对值不超过10^9
思维神题。
考虑对于当前状态的a,b,c有哪些可移动方案,设d1=b-a,d2=c-b,如果d1!=d2,那么b可以向两边跳,d1,d2其中小的那个可以向中间跳;如果d1=d2那么只能由b向两边跳。
可移动方案最多只有三种,那么可以将每个状态看成一个点,往左右跳看作这个点的左右子节点,往中间跳看作是这个点的父节点,如果不能往中间跳,那这个点就是根节点。
那么所有状态就变成了一个二叉树森林,判断能否完成就变成了判断两个状态是否在同一棵树中,而最小步数自然就是两点间的距离了。
但如果将所有状态都枚举出来显然不行,例如下面这个样例:
1 2 1e9
1e9-1 1e9-2 1e9
要跳1e9级别这么多次,显然不能暴力跳。
那么再回到求答案的那一步,两点间的距离不就是lca分别和两点深度差的和吗!
而深度就是每个点跳到根节点的步数。
那么两点往上跳在原题中就是两边的点往中间跳。
因为跳的点和被跳的点之间的相对距离不变,那么就相当于将两个点都平移了两点间距离这么多。
假设d1>d2,那么c最多向左平移(d1-1)/d2次(因为不能跳到同一个点)。
对于d1和d2,我们可以像求gcd一样辗转相除来求得在二叉树上给出的这两点的深度,然后将深度深的点往上跳使两点深度相同。
接下来只要找到深度相同的这两个点的lca就好了,可以像求倍增lca一样往上跳验证,也可以用二分答案来往上跳验证。
我这里用了二分的写法。注意原题三个数不一定按顺序给出。

#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll a,b,c;
ll x,y,z;
ll dep1,dep2;
ll root1,root2;
ll l1,l2;
ll len;
void cmp(ll &a,ll &b,ll &c)
{if(a>b){swap(a,b);}if(a>c){swap(a,c);}if(b>c){swap(b,c);}
}
ll find_root(ll a,ll b,ll c,ll &dep,ll &anc)
{ll d1=b-a;ll d2=c-b;while(d1!=d2){if(d1<d2){ll s=d2/d1;ll t=d2%d1;if(t==0){dep+=(s-1);anc=d1;return a+(s-1)*d1;}else{dep+=s;a+=s*d1;d2=t;}}else{ll s=d1/d2;ll t=d1%d2;if(t==0){dep+=(s-1);anc=d2;return a;}else{dep+=s;d1=t;}}}dep=0;anc=d1;return a;
}
void get_fa(ll &a,ll &b,ll &c,ll dep)
{ll d1=b-a;ll d2=c-b;while(dep>0){if(d1<d2){ll s=d2/d1;ll t=d2%d1;if(s>=dep){a+=dep*d1;b+=dep*d1;if(b==c){b=a;a-=d1;}return ;}else{dep-=s;a+=s*d1;b+=s*d1;d2=t;}}else{ll s=d1/d2;ll t=d1%d2;if(s>=dep){c-=dep*d2;b-=dep*d2;if(a==b){b=c;c+=d2;}return ;}else{dep-=s;b-=s*d2;c-=s*d2;d1=t;}}}
}
int main()
{scanf("%lld%lld%lld",&a,&b,&c);scanf("%lld%lld%lld",&x,&y,&z);cmp(a,b,c);cmp(x,y,z);l1=find_root(a,b,c,dep1,root1);l2=find_root(x,y,z,dep2,root2);if(l1!=l2||root1!=root2){printf("NO");return 0;}if(dep1<dep2){len+=dep2-dep1;get_fa(x,y,z,len);}else{len+=dep1-dep2;get_fa(a,b,c,len);}ll l=0;ll r=min(dep1,dep2);ll ans=0;while(l<=r){ll mid=(l+r)/2;ll a1=a,b1=b,c1=c;ll x1=x,y1=y,z1=z;get_fa(a1,b1,c1,mid);get_fa(x1,y1,z1,mid);if(a1==x1&&b1==y1&&c1==z1){ans=mid;r=mid-1;}else{l=mid+1;}}printf("YES\n");printf("%lld",len+ans*2);
}

转载于:https://www.cnblogs.com/Khada-Jhin/p/9776977.html

BZOJ2144跳跳棋——LCA+二分相关推荐

  1. 跳跳棋[LCA+二分查找]-洛谷1852

    传送门 这真是一道神仙题 虽然我猜到了这是一道LCA的题 但是... 第一遍看题,我是怎么也没想到能和树形图扯上关系 并且用上LCA 但其实其实和上一道lightoj上的那道题很类似 只不过那时一道很 ...

  2. bzoj2144: 跳跳棋(二分/倍增)

    思维好题! 可以发现如果中间的点要跳到两边有两种情况,两边的点要跳到中间最多只有一种情况. 我们用一个节点表示一种状态,那么两边跳到中间的状态就是当前点的父亲,中间的点跳到两边的状态就是这个点的两个儿 ...

  3. [BZOJ2144]跳跳棋

    [BZOJ2144]跳跳棋 试题描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过 ...

  4. bzoj2144 跳跳棋

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...

  5. bzoj-2144 跳跳棋

    2144: 跳跳棋 题目链接 时间限制: 10 Sec 内存限制: 259 MB 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一 个简单的游戏: ...

  6. 洛谷1852 BZOJ2144 跳跳棋 思维题

    题目链接 题意: 坐标轴上告诉你三个互不相同的位置作为三个棋子的起点,再告诉你三个不同的位置作为三个棋子的终点,每次操作可以让一个棋子以另一个棋子为轴跳到对称位置,并且只能跳过一个棋子,问你是否能最终 ...

  7. [bzoj2144]: 跳跳棋

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 689  Solved: 326 [Submit][Status][Discuss ...

  8. BZOJ2144: 跳跳棋

    求三个人从a,b,c这三个位置跳到x,y,z最少多少步.跳:任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子.  从它跳的性质出发,向内跳只有一种操作,而向外跳有两种 ...

  9. BZOJ 2144 跳跳棋(神仙建模题,倍增 LCA,二分)【BZOJ修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2144 是 hydro 的 BZOJ ...

最新文章

  1. 知乎好物推荐玩法介绍
  2. Java入门之包装类
  3. 应用程序-特定 权限设置并未向在应用程序容器 不可用 SID
  4. numpy a[...,:2]
  5. python编程标准_Python常见编程规范总结
  6. php 检查语法命令,php语法检查的方法有哪些?(代码示例)
  7. NTFS系统的访问控制上的权限条目
  8. 《云计算:原理与范式》一3.6 新集成方案
  9. TeamViewer中一些按钮的功能
  10. paip.asp vbs的代码折叠代码结构查看
  11. matlab模拟静电场边值,静电场边值问题有限差分法的仿真分析
  12. 服务器应该选哪家好?
  13. Android开机自动运行
  14. 分布式监控apm_Datadog:APM和分布式跟踪的新Java支持
  15. 如何在Ubuntu上安装OnlyOffice Docs 7.1?
  16. 智能制造数字化工厂的关键技术特点
  17. 79个超强微生物知识,全力助你孕育99分超优宝宝
  18. 4.Java学习笔记第四节——程序流程控制(尚硅谷视频整理)
  19. 在Windows电脑上配置Speedtest测速服务器
  20. CAD中怎么合并设备表?CAD合并设备表操作技巧

热门文章

  1. 吃鸡捡错枪怎么突突突别人?Python用数据告诉你「和平精英」啥枪最合适!
  2. 99%的人都不知道!Python、C、C 扩展、Cython 差异对比!
  3. 分集接收技术性能MATLAB,基于Matlab分集接受性能仿真 .doc
  4. 【观察】西部数据创新存储架构,释放开放计算新力量
  5. 天龙八部手游服务器维护公告,《天龙八部手游》本周例行维护公告
  6. 计算机网络实验软件工具
  7. 建行计算机面试个人介绍,建行面试自我介绍范文
  8. Python按照你的检索爬取天津大学图书馆书籍信息
  9. webappbuilder改为不依赖portal之arcgis for js4.系列
  10. amd处理器不支持slat_如何检查您的CPU是否支持二级地址转换(SLAT)