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] ...
随机推荐
- Sqlserver通过链接服务器访问Oracle的那些事儿
前言: 1.不经历风雨,怎能见彩虹. 2.充分利用BaiDu.google等搜索引擎查找资料并整合分析! 3.世上无难事只怕有心人! 本文由来:笔者在研究SQLSERVER链接服务器到oracle并使 ...
- ORA-01113: file xxxx needs media recovery
由于规范存储位置以及存储空间调整缘故需要移动表空间MRP_INDEX2的数据文件,如下所示,首先将表空间MRP_INDEX2脱机; 然后复制数据文件:接着重命名数据文件,最后将表空间MRP_INDEX ...
- SQL SERVER错误:已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)
在SSMS(Microsoft SQL Server Management Studio)里面,查看数据库对应的表的时候,会遇到"Lock Request time out period e ...
- 一道常被人轻视的前端JS面试题
前言 年前刚刚离职了,分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多 ...
- Centos6下安装Hadoop2.6 问题总结
一. 安装背景:VirtualBox下安装三台Centos6.8虚拟机(一主:master, 两从:slave1,slave2) Centos版本:CentOS-6.8-x86_64 网络配置:三台虚 ...
- ElasticSearch集群设置
多台机器 \config\elasticsearch.yml 文件修改 cluster.name设置统一的集群名如 cluster.name: win-es-001 node.name 设置当前Nod ...
- 防火墙防DDOS攻击的简单设置
#Ping洪水攻击(Ping of Death) iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s - ...
- 利用epoll写一个"迷你"的网络事件库
epoll是linux下高性能的IO复用技术,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率.另一点原因就是获取 ...
- BZOJ1026: [SCOI2009]windy数[数位DP]
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6346 Solved: 2831[Submit][Sta ...
- winform记事本(基本功能)
本题主要考察各种控件的应用 using System; using System.Collections.Generic; using System.ComponentModel; using Sys ...