题目描述

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。

每个点不能摆超过一个棋子。

我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\),\(c\)这三个位置。

我们要通过最少的跳动把他们的位置移动成\(x\),\(y\),\(z\)。(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。

跳动后两颗棋子距离不变。

一次只允许跳过\(1\)颗棋子。

\(a,b,c,x,y,z \le 1e9\)

Input

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

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

Output

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

Sample Input

1 2 3
0 3 5

Sample Output

YES
2

一道非常不错的想法题。

非常强大的建模。。。

对于一个状态\((a,b,c)\),我们保证\(a \le b \le c\);

对于当前状态\((a,b,c)\)可以转移的状态为

中间的\(b\)往两边跳,即\((2*a-b,b,c)\)和\((a,b,2*c-b)\)为\((a,b,c)\)的子节点。

由于,一个棋子只能跳过一个棋子。

所以,\((a,b,c)\)由两边的棋子跳动的转移,只能由距离中轴最近的棋子跳动,将其状态定义为其父亲节点。

由此,我们可以把一个状态到另一个状态的过程转换为树上一个节点到另一个节点的距离。

很显然我们只知道初状态和末状态。

我们并不知道树上的所有节点,因此,我们不能直接利用常规方法求\(LCA\)。

但是我们发现,我们可以求出一个节点的\(K\)祖先的状态。

由此,我们可以将一个节点移至于另一个节点深度相同的位置。

再二分答案,二分两个节点向上走的步数。

现在,问题成功转换为如何快速的求出一个节点的\(k\)祖先的状态。

我们可以发现设前两个数的差值为\(t_1\),后两个数的差值为\(t_2\),

左边的节点最多往右边跳\((t_2-1)/t_1\)次,然后变成右边跳。

这是一个辗转相除的过程,时间复杂度为\(O(log{n})\),问题也就解决了。

详见代码。

代码如下

#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; #define LL long long
#define reg register
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,x) for(reg int i=Head[x]; i; i=Nxt[i]) inline int Read() {
int res = 0, f = 1;
char c;
while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
do res = (res << 3) + (res << 1) + (c ^ 48);
while (c = getchar(), c >= 48 && c <= 57);
return f ? res : -res;
} template<class T>inline bool Min(T &a, T const&b) {
return a > b ? a = b, 1 : 0;
}
template<class T>inline bool Max(T &a, T const&b) {
return a < b ? a = b, 1 : 0;
} const int N = 20, M = 5e5 + 5; struct node {
int A[4];
bool operator!=(node _)const {
rep(i, 1, 3)if (A[i] != _.A[i])return true;
return false;
}
}; int tot; node Find(int *A, int step) {
node Ans;
rep(i, 1, 3)Ans.A[i] = A[i];
int step1 = A[2] - A[1], step2 = A[3] - A[2];
if (step1 == step2)return Ans;
if (step1 < step2) {
int t = min(step, (step2 - 1) / step1);
step -= t, tot += t;
Ans.A[1] += t * step1, Ans.A[2] += t * step1;
} else {
int t = min(step, (step1 - 1) / step2);
step -= t, tot += t;
Ans.A[2] -= t * step2, Ans.A[3] -= t * step2;
}
if (step)return Find(Ans.A, step);
else return Ans;
} int A[5], B[5];
signed main(void) {
rep(i, 1, 3)A[i] = Read();
rep(i, 1, 3)B[i] = Read();
sort(A + 1, A + 4), sort(B + 1, B + 4);
node a = Find(A, 1e9); int step1 = tot; tot = 0;
node b = Find(B, 1e9); int step2 = tot; tot = 0;
if (a != b)return !puts("NO");
if (step1 > step2) {
swap(step1, step2);
rep(i, 1, 3)swap(A[i], B[i]);
}
int Ans = step2 - step1;
node T = Find(B, Ans);
rep(i, 1, 3)B[i] = T.A[i];
int L = 0, R = step1;
while (L <= R) {
int mid = (L + R) >> 1;
if (Find(A, mid) != Find(B, mid)) L = mid + 1;
else R = mid - 1;
}
puts("YES");
printf("%d", Ans + 2 * L);
return 0;
}

[BZOJ2144][国家集训队2011]跳跳棋的更多相关文章

  1. AC日记——[国家集训队2011]旅游(宋方睿) cogs 1867

    [国家集训队2011]旅游(宋方睿) 思路: 树链剖分,边权转点权: 线段树维护三个东西,sum,max,min: 当一个区间变成相反数时,sum=-sum,max=-min,min=-max: 来, ...

  2. cogs 1901. [国家集训队2011]数颜色

    Cogs 1901. [国家集训队2011]数颜色 ★★★   输入文件:nt2011_color.in   输出文件:nt2011_color.out   简单对比时间限制:0.6 s   内存限制 ...

  3. BZOJ 2150 cogs 1861 [国家集训队2011]部落战争

    题目描述 lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把 ...

  4. bzoj2144 【国家集训队2011】跳跳棋

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

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

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

  6. happiness[国家集训队2011(吴确)]

    [试题来源] 2011中国国家集训队命题答辩 [问题描述] 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科 ...

  7. COGS1882 [国家集训队2011]单选错位

    ★   输入文件:nt2011_exp.in   输出文件:nt2011_exp.out   简单对比时间限制:1 s   内存限制:512 MB [试题来源] 2011中国国家集训队命题答辩 [问题 ...

  8. 1893. [国家集训队2011]等差子序列(bitset)

    ★★   输入文件:nt2011_sequence.in   输出文件:nt2011_sequence.out   简单对比时间限制:0.3 s   内存限制:512 MB [试题来源] 2011中国 ...

  9. COGS.1901.[模板][国家集训队2011]数颜色(带修改莫队)

    题目链接 COGS BZOJ2120 洛谷P1903 /* Add和Subd函数中的vis不能直接设为=1或=0 比如 l=1,r=0 -> l=3,r=5 时,[1,5]的vis标记全都是1 ...

随机推荐

  1. ASE高级软件工程 第一次结对作业

    黄金点游戏Bot Bot8前来报道 1.问题定义 a) 问题描述 N个玩家,每人写一个0~100之间的有理数 (不包括0或100),提交给服务器,服务器在当前回合结束时算出所有数字的平均值,然后乘以0 ...

  2. mysql内存分配问题

    云数据库 MySQL 的内存是重要的性能参数,常出现由异常 SQL 请求以及待优化的数据库导致的内存利用率升高的情况,严重时还会出现由于 OOM 导致实例发生 HA 切换,影响业务的稳定及可用性. M ...

  3. 我不熟悉的set

    同样的我着重介绍那些我不怎么用到的系列,同时,常用的我就点一下. 我们都知道set底层是用红黑树实现的,红黑树是一种已排序的树,所以我们通过迭代器来访问节点元素的时候,并不可以改变它,如果随意改变,那 ...

  4. scala实战学习-尾递归函数

    求 $$ \Sigma\sideset{^b_a}f(x) $$ object sumfunc{ def sum(f: Int => Int)(a: Int)(b:Int): Int = { @ ...

  5. Spring Boot使用阿里云证书启用HTTPS

    1.到阿里云下载证书页面下载证书 2.根据页面内容,可以使用2种证书:PFX JKS 把对应证书放到src/main/resources目录下 在application.properties文件中加入 ...

  6. 使用asio进行异步下载http

    下面是官方demo, 给人耳目一新的感觉,以前是总是把c++当成有类功能的C,看完这个感觉不用自己造轮子了,还是要跟上时代的步伐 // // async_client.cpp // ~~~~~~~~~ ...

  7. leetcode-easy-listnode-234 Palindrome Linked List

    mycode   89.42% # Definition for singly-linked list. # class ListNode(object): # def __init__(self, ...

  8. Learn The Architecture Memory Management 译文

    1.概述 本文档介绍了ARMv8-A架构内存管理的关键——内存地址转换,包括虚拟地址(VA)到物理地址(PA)的转换.页表(或称地址转换表)格式以及TLBs(Translation Lookaside ...

  9. P2239 螺旋矩阵

    P2239 螺旋矩阵 题解 这题看上去是个暴力,但是你看数据范围啊,暴力会炸 实际上这是一道数学题QWQ 先看看螺旋矩阵是个什么亚子吧 好吧,找找规律 1 2 ... ... ... ... ... ...

  10. 新建一个浏览器APP

    安卓开发环境准备好了,试试新建一个浏览器程序吧 1.Start a new Android Studio Project 2.选这个像微信一样的样式 3.选择语言和版本 4.等待创建完成,拖一个Web ...