【BZOJ2144】跳跳棋 模拟gcd以及倍增LCA

#include <stdio.h>
int main()
{
	puts("转载请注明出处谢谢");
	puts("http://blog.csdn.net/vmurder/article/details/43235053");
}

题意:首先一个状态至多有3种跳的方法的~不能隔着格子跳的~

题解:

既然有三种方法,那么显然有两种是向外跳,一种是收敛着跳(往里)

然后这个就可以类比成父亲状态和子状态,

里兮为父,外则即子。(诶窝里斗的感觉,,这文言文有点喜感)

然后我们就发现步数是开始状态和结束状态都往里走,走到lca的步数。

或者说开始状态走到lca,然后再由lca走到结束状态。。

代码跟思路是一样的:(有详细注释~)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 5
#define inf 0x3f3f3f3f
using namespace std;
struct Status
{
	int x[N];
	void read(){for(int i=1;i<=3;i++)scanf("%d",&x[i]);}
	bool operator != (const Status &a)const
	{return x[1]!=a.x[1]||x[2]!=a.x[2]||x[2]!=a.x[2];}
}S,T;
Status cal(const Status &a,int k,int &ret) // 跳k次
{
	Status ans=a;
	int i,j,dis1=a.x[2]-a.x[1],dis2=a.x[3]-a.x[2];
	if(dis1==dis2)return ans;
	else if(dis1<dis2)
	{
		int t=min(k,(dis2-1)/dis1);   // 往父亲状态跳跳跳跳。
									 // t是需要跳的次数(跳到头)
									// -1 是避免跳重合了
		k-=t,ret+=t;
		ans.x[2]+=t*dis1,ans.x[1]+=t*dis1;
		  // 第一枚棋子未必还是第一枚
		 // 第二枚棋子也未必还是第二枚了。
		// 算是又排好序了吧(画一下t是奇数的情况,比如t==1)
	}
	else // 同上,情况讨论而已
	{
		int t=min(k,(dis1-1)/dis2);
		k-=t,ret+=t;
		ans.x[2]-=t*dis2,ans.x[3]-=t*dis2;
	}

	if(k)return cal(ans,k,ret);
	else return ans;
}
int dis1,dis2,ans;
int main()
{
//	freopen("test.in","r",stdin);

	int i,j,k,temp=0;
	S.read(),T.read();
	sort(S.x+1,S.x+4);
	sort(T.x+1,T.x+4);

	int reta=0,retb=0;
	Status final_s=cal(S,inf,reta),final_t=cal(T,inf,retb);

	if(final_s!=final_t){puts("NO");return 0;}
	 // 棋子方案可以构造成森林~
	// 所以需要两个状态是一个父亲~~
	else {
		puts("YES");
		if(reta>retb)
		{
			swap(reta,retb);
			swap(S,T);
		}// 我们让T更深!
		ans=retb-reta;
		T=cal(T,ans,temp); 	 // 模拟倍增LCA的过程
							// 我们会先让两者深度相同
		int l=0,r=reta,mid;
		while(l<=r) // 诶一样的。
		{
			mid=l+r>>1;
			if(cal(S,mid,temp)!=cal(T,mid,temp))l=mid+1;
			else r=mid-1;
		}
		printf("%d\n",ans+2*l);  // 肯定得先到lca再变换的
								// 不会有更优解了~~~
	}
	return 0;
}
时间: 2024-11-18 08:08:43

【BZOJ2144】跳跳棋 模拟gcd以及倍增LCA的相关文章

bzoj2144 跳跳棋

Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子.  写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. Input 第一行包含三个整数,表示当前棋子的位置a b c.(互不相同)

bzoj2144 跳跳棋 二分

[bzoj2144]跳跳棋 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子.  写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. Input 第一行包含三个整数,表示当前棋子的

跳跳棋bzoj2144国家集训队

题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的) 跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子. 写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. 输入输出格式 输入格式: 第一行包含三个整数,表示当前棋子的位置a b c.(互不相同

跳跳棋(9018_1563)(BZOJ_2144)

题目: Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们要通过最少的跳动把它们的位置移动成x,y,z.(棋子是没有区别的) 跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子. 写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. 这道题的状态是可以在树上处理的,对于一个中间到两端距离不

BZOJ 2144 跳跳棋

2144: 跳跳棋 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动成x,y,z.(棋子是没有区别的)跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动.跳动后两颗棋子距离不变.一次只允许跳过1颗棋子.  写一个程序,首先判断是否可以完成任务.如果可以,输出最少需要的跳动次数. Input 第一行包含三个整数,表示当前棋子的位置a

【Luogu】P1967货车运输(最大生成森林+倍增LCA)

题目链接 倍增LCA是个什么蛇皮原理啊,循环完了还得再往上跳一次才能到最近公共祖先 合着我昨天WA两次就是因为这个 建最大生成森林,因为图不一定是联通的,所以不一定是一棵树.这个地方用克鲁斯卡尔就好了 然后给这个森林跑一遍DFS,顺便倍增 然后对于每个询问跑LCA,倍增的时候已经顺便求出了最小边权,所以往上跳的同时更新答案. 代码如下 #include<cstdio> #include<cctype> #include<cstdlib> #include<cmat

[HNOI2014][BZOJ3572] 世界树|虚树|树上倍增LCA|树型dp|dfs序

3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 555  Solved: 319[Submit][Status][Discuss] Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持续运转的根本基石.    世界树的形态可以用一个数学模型来描述:世界树中有n个种

bzoj-2286 消耗战【虚树+倍增lca+单调栈】

2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 1815  Solved: 645 [Submit][Status][Discuss] Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是

洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

洛谷题目传送门 %%%天平巨佬和山楠巨佬%%% 他们的题解 思路分析 具体思路都在两位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 首先kruskal把最小生成树弄出来,因为要求次小生成树.至于为什么次小一定只在最小的基础上改变了一条边,我也不会证......打表找规律大法好 剩下的可以有一堆数据结构来维护最大值和次大值(原理两位巨佬都讲清楚了,这里只分析一下算法的优劣) 倍增+LCA 山楠巨佬的做法,我也写了这一种.复杂度\(O(MlogM(kruscal)+MlogN(