BZOJ2144: 跳跳棋
神题一道。
考虑题目性质。首先对于一个状态,只存在四种情况,即最左/右边的点跳到中间,中间的点跳到左/右。而对于一个状态,显然第一种情况的两种分支不能同时存在,那么题目就可以理解为从$(a,b,c)$找到一条最短的路径可以使得其到达$(x,y,z)$,你完全可以把所有状态存下来随便跑个最短路算法,但是显然是无法承受的,而再研究题目可以发现如果根据一个状态的情况连边,所形成的图是一棵树,而且还是个二叉树,那么就可以利用这个性质。那么假设现在一个状态是$(x,y,z)$,设$t1=y-x,t2=z-y$。如果$t1==t2$,那么就代表这个节点是个根节点。为了简化题目,不考虑每个节点的儿子情况,只考虑他的父亲,那么这个题目就可以看作在一棵树里找两个点的LCA。那么如何求一个节点的第$k$个祖先?
根据gcd的一些奇奇怪怪的性质,可以发现如果$t1>t2$,那么不断将最左边的点移到中间,最多可以移$\frac{t1-1}{t2}$,根据这个也很容易算出移动后的状态。
剩下的就很好搞了, 倍增二分什么的都可以,我用的是二分。
//BZOJ 2144
//by Cydiater
//2016.10.20
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <cstdlib>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int dep1,dep2,ans=0;
struct Node{
int x,y,z;
void Sort(){if(x>y)swap(x,y);if(x>z)swap(x,z);if(y>z)swap(y,z);}
}a,b;
bool operator == (Node x,Node y){return x.x==y.x&&x.y==y.y&&x.z==y.z;}
namespace solution{
void init(){
a.x=read();a.y=read();a.z=read();
b.x=read();b.y=read();b.z=read();
}
int get(Node node){
int x=node.x,y=node.y,z=node.z;
int t1=abs(y-x),t2=abs(z-y),Ans=0;
while(t1!=t2&&t1*t2!=0){
if(t1<t2)swap(t1,t2);
Ans+=(t1-1)/t2;
int tmp=t1;t1=t2;t2=tmp%t2;
}
return Ans;
}
Node jump(Node t,int dist){
if(get(t)<dist)return (Node){oo,oo,oo};
t.Sort();
while(dist){
if(t.y-t.x>t.z-t.y){
int t1=t.y-t.x,t2=t.z-t.y;
if((t1-1)/t2<dist){
dist-=(t1-1)/t2;
t.y-=(t1-1)/t2*t2;
t.z-=(t1-1)/t2*t2;
}else{
t.y-=dist*t2;
t.z-=dist*t2;
dist=0;
}
}else{
int t1=t.y-t.x,t2=t.z-t.y;
if((t2-1)/t1<dist){
dist-=(t2-1)/t1;
t.x+=(t2-1)/t1*t1;
t.y+=(t2-1)/t1*t1;
}else{
t.x+=dist*t1;
t.y+=dist*t1;
dist=0;
}
}
}
return t;
}
void slove(){
if(a==b){puts("YES");puts("0");return;}
a.Sort();b.Sort();
dep1=get(a);dep2=get(b);
if(dep1<dep2){swap(a,b);swap(dep1,dep2);}
ans+=dep1-dep2;
a=jump(a,dep1-dep2);
if(a.x==oo){puts("NO");return;}
if(a==b){puts("YES");cout<<ans<<endl;return;}
int leftt=1,rightt=1000000000,mid;
while(leftt+1<rightt){
mid=(leftt+rightt)>>1;
if(jump(a,mid)==jump(b,mid))rightt=mid;
else leftt=mid;
}
if(jump(a,leftt)==jump(b,leftt)&&jump(a,leftt).x!=oo){
puts("YES");
printf("%d\n",ans+(leftt<<1));
}
else if(jump(a,rightt)==jump(b,rightt)&&jump(a,rightt).x!=oo){
puts("YES");
printf("%d\n",ans+(rightt<<1));
}
else puts("NO");
}
}
int main(){
//freopen("input.in","r",stdin);
using namespace solution;
init();
slove();
return 0;
}
BZOJ2144: 跳跳棋的更多相关文章
- bzoj2144 跳跳棋 二分
[bzoj2144]跳跳棋 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位 ...
- BZOJ2144跳跳棋——LCA+二分
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的 游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...
- bzoj2144: 跳跳棋(二分/倍增)
思维好题! 可以发现如果中间的点要跳到两边有两种情况,两边的点要跳到中间最多只有一种情况. 我们用一个节点表示一种状态,那么两边跳到中间的状态就是当前点的父亲,中间的点跳到两边的状态就是这个点的两个儿 ...
- BZOJ2144 跳跳棋[建模+LCA]
思维题,思路比较神仙. 个人思路过程:个人只想到了只要中间棋子开始向外跳了,以后就不应该向内跳了,这样很蠢.所以应该要么先向内跳一会,要么直接开始中间的向外跳.不知道怎么处理,就卡住了. 20pts: ...
- bzoj2144 【国家集训队2011】跳跳棋
Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...
- 【bzoj2144】跳跳棋
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 492 Solved: 244[Submit][Status][Discuss] ...
- [BZOJ2144]国家集训队 跳跳棋
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...
- [BZOJ2144][国家集训队2011]跳跳棋
题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上. 每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\),\(c\)这三个位置. 我们要通 ...
- 【LCA】bzoj 2144:跳跳棋
2144: 跳跳棋 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 248 Solved: 121[Submit][Status][Discuss] ...
随机推荐
- MS SQL错误:SQL Server failed with error code 0xc0000000 to spawn a thread to process a new login or connection. Check the SQL Server error log and the Windows event logs for information about possible related problems
早晨宁波那边的IT人员打电话告知数据库无法访问了.其实我在早晨也发现Ignite监控下的宁波的数据库服务器出现了异常,但是当时正在检查查看其它服务器发过来的各类邮件,还没等到我去确认具体情 ...
- 解决session阻塞的问题
简介 对于数据库运维人员来说创建session或者查询时产生问题是常规情况,下面介绍一种很有效且不借助第三方工具的方式来解决类似问题. 最近开始接触运维工作,所以自己总结一些方案便于不懂数据库的同事解 ...
- django ORM
http://www.cnblogs.com/alex3714/articles/5512568.html 常用ORM操作 一.示例Models from django.db import model ...
- W3School-CSS 分类 (Classification) 实例
CSS 分类 (Classification) 实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) ...
- Java读写文本文件操作
package com.test; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; ...
- 直播时代--IOS直播客户端SDK,美颜直播【开源】
当前视频直播非常火爆,手机端的视频直播也非常火爆,PGC.UGC的视频直播门槛都降低了很多. 本文介绍一个:IOS 客户端直播的SDK,代码完全开源. 直播时代:让IOS普通开发者一天内做出一个RTM ...
- [转]jquery append 动态添加的元素事件on 不起作用的解决方案
用jquery添加新元素很容易,面对jquery append 动态添加的元素事件on 不起作用我们该如何解决呢?on方法中要先找到原选择器(如例.info),再找到动态添加的选择器(如列.delet ...
- FeWeb基础之HTML
FeWeb基础之HTML 1.HTML简介 HTML是一种超文本标记语言,它的文件扩展名为.html,它的所有部分都是由标记<...>和标记</...>包括起来. 在一个HTM ...
- Workerman-文件监控-牛刀小试
今天学习了workerman , 初次体验了定时器的效果,结合文档.弄了个文件监控. 好了 废话不多说 直接上代码 use Workerman\Worker; require_once __DIR__ ...
- Linux吃掉我的内存
在Windows下资源管理器查看内存使用的情况,如果使用率达到80%以上,再运行大程序就能感觉到系统不流畅了,因为在内存紧缺的情况下使用交换分区,频繁地从磁盘上换入换出页会极大地影响系统的性能.而当我 ...