P1852 跳跳棋(建模&LCA)

往外跳有个两个状态,往里跳只能有一个唯一父亲状态。

所以是一个二叉树。

将给定的起始和目标状态 向上找到根,判断是否相等。不相等无解。

否则类似求LCA的思想二分步数即可。

// Problem: P1852 跳跳棋
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1852
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-30 09:43:38
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
struct node{
	int a[3];
	bool operator != (node  b)const{
		for(int i=0;i<3;i++) if(a[i]!=b.a[i]) return true;
		return false;
	}
}A,B;
int tmp;
node fun(node A,int k){
	int d1=A.a[1]-A.a[0],d2=A.a[2]-A.a[1];
	if(d1==d2) return A;
	else if(d1<d2){
		int t=min(k,(d2-1)/d1);
		k-=t;
		tmp+=t;
		A.a[0]+=t*d1,A.a[1]+=t*d1;
	}
	else {
		int t=min(k,(d1-1)/d2);
		k-=t;
		tmp+=t;
		A.a[1]-=t*d2,A.a[2]-=t*d2;		
	}
	if(k) return fun(A,k);
	else return A;
}
int main(){
	for(int i=0;i<3;i++) scanf("%d",&A.a[i]);
	for(int i=0;i<3;i++) scanf("%d",&B.a[i]);
	sort(A.a,A.a+3);
	sort(B.a,B.a+3);
	int dep1=0,dep2=0;
	node na=fun(A,inf);dep1=tmp,tmp=0;
	node nb=fun(B,inf);dep2=tmp,tmp=0;
	if(na!=nb) return puts("NO"),0;
	if(dep1>dep2){
		swap(dep1,dep2);
		swap(A,B);
	}
	int ans=dep2-dep1;
	B=fun(B,ans);
	int l=0,r=dep1;
	while(l<r){
		int m=l+r>>1;
		if(fun(A,m)!=fun(B,m)) l=m+1;
		else r=m;
	}
	ans+=(l<<1);
	puts("YES");
	printf("%d\n",ans);
	return 0;
}