跳跳棋 LCA 二分

2021-10-09 07:49:12 字數 3074 閱讀 6150

>description

跳跳棋是在一條數軸上進行的。棋子只能擺在整點上。每個點不能擺超過乙個棋子。

我們用跳跳棋來做乙個簡單的遊戲:棋盤上有3顆棋子,分別在a,b,c這三個位置。我們要通過最少的跳動把他們的位置移動成x,y,z。(棋子是沒有區別的)

跳動的規則很簡單,任意選一顆棋子,對一顆中軸棋子跳動。跳動後兩顆棋子距離不變。一次只允許跳過1顆棋子。

寫乙個程式,首先判斷是否可以完成任務。如果可以,輸出最少需要的跳動次數。

>input

第一行包含三個整數,表示當前棋子的位置a b c。(互不相同)

第二行包含三個整數,表示目標位置x y z。(互不相同)

>output

如果無解,輸出一行no。

如果可以到達,第一行輸出yes,第二行輸出最少步數。

>sample input

1 2 3

0 3 5

>sample output

yes2

20% 輸入整數的絕對值均不超過10

40% 輸入整數的絕對值均不超過10000

100% 絕對值不超過10^9

>解題思路

題目大意:有乙個線性的跳棋,問三個點的狀態

a,b,

c}能否到達,並且輸出最小步數

設為s

1s_1

s1​,為s

2s_2

s2​通過手動模擬可以發現,一組資料,a

<

ba<

b<

c,可以達到三種狀態:

b

bb向a

aa的方向跳

b

bb向c

cc的方向跳

離b

bb近的點往b

bb的方向跳,且當僅當b−a

≠c−b

b-a≠c-b

b−a​=

c−b(三個點均勻分布,這樣子就跳不動)

我們可以發現1、2種跳的方法是擴大範圍,第3種是縮小範圍,所以我們可以把第3種設為根,把第1、2種設為兩個子節點,因此b−a

==c−

bb-a==c-b

b−a==c

−b的狀態為根節點

如果s

1s_1

s1​和s

2s_2

s2​的根節點相同,就說明s

1s_1

s1​可以到達s

2s_2

s2​所以我們可以進行以下步驟:

往上跳,分別尋找s

1s_1

s1​,s

2s_2

s2​的根,判斷這兩個根節點是否相等

把s

1s_1

s1​和s

2s_2

s2​跳到同一高度

二分向上跳的步數,看兩個狀態跳躍以後分別達到的狀態是否相同

這裡有乙個很重要的加速:

如果是這種距離很長的情況,可以直接用除數加速,當然要注意重合的情況

例如設d1=

b−ad_1=b-a

d1​=b−

a,d2=c

−bd_2=c-b

d2​=c−

b,可以直接用d1/

d2d_1/d_2

d1​/d2

​加速>**

#include
#include

#include

#include

using namespace std;

struct node

s1, s2, root[5]

;int dep[5]

;bool check

(node aa, node bb)

void

ssort

(node &aa)

//排序

void

getroot

(node aa, int ll)

else

dep[ll]

+= l;

//累計狀態在樹中的深度

ssort

(aa);}

root[ll]

=(node);}

//找根

node jump

(node aa, int k)

//狀態aa往上跳k步達到的狀態

else

k -= l;

ssort

(aa);}

return aa;

}int main()

int d =

abs(dep[1]

- dep[2]

);//初始狀態和最終狀態相差的深度

if(dep[1]

> dep[2]

) s1 =

jump

(s1, d)

;else

if(dep[1]

< dep[2]

) s2 =

jump

(s2, d)

;//把深度深的跳到和深度淺的同一層

int l =

0, r =

min(dep[1]

, dep[2]

), mid;

int m =0;

while

(l <= r)

printf

("yes\n%d"

, d +

2* m)

;//兩點到lca的路徑長度

return0;

}

跳跳棋 二分 建模LCA

跳跳棋是在一條數軸上進行的。棋子只能擺在整點上。每個點不能擺超過乙個棋子。我們用跳跳棋來做乙個簡單的遊戲 棋盤上有3顆棋子,分別在a,b,c這三個位置。我們要通過最少的跳動把他們的位置移動成x,y,z。棋子是沒有區別的 跳動的規則很簡單,任意選一顆棋子,對一顆中軸棋子跳動。跳動後兩顆棋子距離不變。一...

BZOJ 2144 跳跳棋 二分 LCA

description 跳跳棋是在一條數軸上進行的。棋子只能擺在整點上。每個點不能擺超過乙個棋子。我們用跳跳棋來做乙個簡單的遊戲 棋盤上有3顆棋子,分別在a,b,c這三個位置。我們要通過最少的跳動把他們的位置移動成x,y,z。棋子是沒有區別的 跳動的規則很簡單,任意選一顆棋子,對一顆中軸棋子跳動。跳...

LCA 二分 倍增

兩個最近的點u和v的最近的公共的祖先稱為最近公共祖先 lca 普通的lca演算法,每算一次lca的時間複雜度為線性o n 這裡講lca 二分的方法。首先對於任意的節點v,利用其父節點的資訊,可以通過par2 v par par v 得到向上走兩步的節點。依此資訊可以通過par4 v par2 par...