P1852 [国家集训队]跳跳棋

题目背景

原《奇怪的字符串》请前往 P2543

题目描述

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。

我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)

跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。

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

输入输出格式

输入格式:

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

第二行包含三个整数,表示目标位置x y z。(互不相同)

输出格式:

如果无解,输出一行NO。

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

输入输出样例

输入样例#1: 复制

1 2 3
0 3 5
输出样例#1: 复制

YES
2

说明

20% 输入整数的绝对值均不超过10

40% 输入整数的绝对值均不超过10000

100% 绝对值不超过10^9


Solution

然而并不想写solution....

是一道建模题,谁能想到这道题和树可以扯上关系????

把起点和终点状态拟成树上的两个节点,就像树上求链的长度一样找lca并且把两个节点到lca的距离加起来得到答案。

听起来好玄乎??

更玄乎的是这种找lca的方法和倍增惊人地相似!

想要找到中间作为lca的转折状态,一步一步跳显然不行。由此观察题目本身的性质,给出的三个棋子是完全相同的,那么把一个作为中轴跳相当于把这两个棋子一起平移他们之间的距离。

这样可以快速地找到某一状态一直跳到不能跳时每个棋子的位置。所以首先判断如果给出的两个状态的最终状态不相同,那么输出‘NO’

所以我们还发现,两种状态跳到他们最终状态的步数的差就是它们‘深度’的差,就像倍增求lca先要把深度调成一样再一起往上跳。

所以先处理出以上需要的东西,有点像辗转相除??每次都尽量跳到不能跳,然后交换继续跳。

将两个状态深度调到一样后,一起向上跳的步数就可以用二分,每次check往上跳看是否跳到一样。

二分出的答案要乘2(链)加上深度调到一样的答案即可。

Code

#include<bits/stdc++.h>
#define LL long long
using namespace std; LL dep1, dep2, a, b, c, x, y, z, ans; LL get_root(LL a, LL b, LL c, LL &dep, LL &l) {
LL d1 = b - a, d2 = c - b;
while(d1 != d2) {
if(d2 > d1) {
LL s = d2 / d1, dis = d2 % d1;
if(!dis) {
dep += s - ;
l = d1; return a + (s - ) * d1;
}
dep += s; a += s * d1; b += s * d1;
d2 = dis;
} else {
LL s = d1 / d2, dis = d1 % d2;
if(!dis) {
dep += s - ;
l = d2; return a;
}
dep += s; b -= s * d2; c -= s * d2;
d1 = dis;
}
}
dep = ; l = d1; return a;
} void Swap(LL &a, LL &b, LL &c) {
if(a > b) swap(a, b);
if(a > c) swap(a, c);
if(b > c) swap(b, c);
} void find_fa(LL &a, LL &b, LL &c, LL step) {
while(step) {
LL d1 = b - a, d2 = c - b;
if(d2 > d1) {
LL s = d2 / d1;
if(s >= step) {
a += step * d1; b += step * d1;
return ;
}
a += s * d1; b += s * d1; step -= s;
} else {
LL s = d1 / d2;
if(s >= step) {
c -= step * d2; b -= step * d2;
return ;
}
c -= s * d2; b -= s * d2; step -= s;
}
}
} void solve() {
LL l = , r = min(dep2, dep1);
LL st;
while(l <= r) {
LL mid = (l + r) >> ;
LL aa = a, bb = b, cc = c;
LL xx = x, yy = y, zz = z;
find_fa(aa, bb, cc, mid);
find_fa(xx, yy, zz, mid);
if(aa == xx && bb == yy && cc == zz) st = mid, r = mid - ;
else l = mid + ;
}
printf("%lld", ans + st * );
} int main() {
scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &x, &y, &z);
Swap(a, b, c); Swap(x, y, z);
LL del1, del2;
LL pos1 = get_root(a, b, c, dep1, del1);
LL pos2 = get_root(x, y, z, dep2, del2);
if(del1 != del2 || pos1 != pos2) {
puts("NO"); return ;
}
puts("YES");
if(dep1 > dep2) {
ans += dep1 - dep2;
find_fa(a, b, c, dep1 - dep2);
} else if(dep2 > dep1) {
ans += dep2 - dep1;
find_fa(x, y, z, dep2 - dep1);
}
solve();
}

【洛谷】1852:[国家集训队]跳跳棋【LCA】【倍增?】的更多相关文章

  1. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

  2. 洛谷 P1852 [国家集训队] 跳跳棋

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

  3. P1852 [国家集训队]跳跳棋

    P1852 [国家集训队]跳跳棋 lca+二分 详细解析见题解 对于每组跳棋,我们可以用一个三元组(x,y,z)表示 我们发现,这个三元组的转移具有唯一性,收束性 也就是说,把每个三元组当成点,以转移 ...

  4. 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)

    洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...

  5. 洛谷 3379 最近公共祖先(LCA 倍增)

    洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include &l ...

  6. [洛谷P1527] [国家集训队]矩阵乘法

    洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...

  7. [BZOJ2144]国家集训队 跳跳棋

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

  8. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  9. 洛谷P2619 [国家集训队2]Tree I(带权二分,Kruscal,归并排序)

    洛谷题目传送门 给一个比较有逼格的名词--WQS二分/带权二分/DP凸优化(当然这题不是DP). 用来解决一种特定类型的问题: 有\(n\)个物品,选择每一个都会有相应的权值,需要求出强制选\(nee ...

随机推荐

  1. 【日记】NOIP2018

    day-2: 最后一次走出机房,刚下过几天的雨,感受到的是彻骨的寒意.下午离开教室,跟班主任请了接下来几天的假,班主任斜视了我一眼,哼了一声,确认了一下,不再理会我了.班里的同学或是忙着自己的作业,或 ...

  2. CentOS系统时间与现在时间相差8小时解决方法

    很多网友在安装完CentOS系统后发现时间与现在时间相差8小时,这是由于我们在安装系统的时选择的时区是上海,而CentOS默认bios时间是utc时间,所以时间相差了8小时.这个时候的bios的时间和 ...

  3. JAVA复习笔记分布式篇:zookeeper

        前言:终于到分布式篇,前面把JAVA的一些核心知识复习了一遍,也是一个JAVA程序员最基本要掌握的知识点,接下来分布式的知识点算是互联网行业的JAVA程序员必备的技能:     概念:ZooK ...

  4. COLLATE CHINESE_PRC_CI_AS_WS 的含义

    排序规则:COLLATE CHINESE_PRC_CI_AS_WS 的含义 在创建数据表时,常会用到这个. 含义当中,CHINESE_prc_ 是代表中国大陆.如果是台湾,则如:Chinese_TAI ...

  5. Linux基础入门学习笔记之二

    第三节 用户及文件权限管理 Linux用户管理 Linux是可以实现多用户登录的操作系统 查看用户 who命令用于查看用户 shiyanlou是当前登录用户的用户名 pts/0中pts表示伪终端,后面 ...

  6. SCTF 2014 PWN400 分析

    之前没有分析PWN400,现在再开一篇文章分析一下. 这个日志是我做题的一个笔记,就是说我做一步题就记录一下是实时的.所以说可能会有错误之类的. 首先程序是经典的笔记本程序,基本上一看到这种笔记本就知 ...

  7. JavaScript中的数据结构及实战系列

    本系列主要是讲解JavaScript中的数据结构及在实际项目中遇到的地方 JavaScript中的数据结构及实战系列(1):队列 JavaScript中的数据结构及实战系列(2):栈

  8. Asp.net Vnext 中间件实现基本验证

    概述 本文已经同步到<Asp.net Vnext 系列教程 >中] vnext 没有 web.config 可以配置基本验证,本文使用中间件实现基本验证 实现 通过Startup(启动类) ...

  9. PHP递归遍历数组 不破坏数据结构 替换字符

    代码如下: <?php $arr = array('0'=>array("<小刚>","<小晓>","<小飞 ...

  10. mysql远程访问 登录ERROR 1130: is not allowed to connect to this MySQL server解决办法

    LINUX6.3 里装了mysql5.0.18 版本运行服务器. 提示错误为: ERROR 1130: Host '192.168.0.102' is not allowed to connect t ...