luogu P1852 國家集訓隊 跳跳棋

2022-02-04 21:29:34 字數 1122 閱讀 3968

luogu

直接操作是不可能的,考慮發現一些性質.可以發現如果每次跳的棋子都是兩邊的,那麼最多只有一種方案,那麼就把這樣操作得到的狀態記為當前狀態的父親,從乙個狀態這樣做一定會結束.那麼如果兩個狀態只操作兩邊到達的最終狀態相同,那麼就可以互相轉換

步數的話,如果把這個看成一棵樹,那麼就是乙個樹上距離問題,就要求出這兩個狀態在樹上的深度以及他們lca的深度.這個操作直接模擬是不行的,不過如果把中間的棋子座標和左邊座標差記為\(a\),右邊的和中間的差記為\(b\)(這裡假設\(a>b\),反之類似),那麼每次操作後會得到\((a-b,b)\),操作若干次後得到\((a\mod b,b)\)(如果\(b|a\)就是\((b,b)\)),然後會進行反向操作直到\(a=b\),所以每次只要從\((a,b)\)走到\((a\mod b,b)\)就好了,最多隻會走\(log n\)次,然後到達根的距離也可以順帶算出來.lca的話就把兩個狀態的父親按順序記到棧裡,每次彈棧頂彈到最後乙個相同元素,不過注意可能真正的lca可能並不是\((a\mod b,b)\),所以還要稍微討論一下

#include#define ll long long

#define ull unsigned long long

#define db double

using namespace std;

const int inf=1<<30;

int rd()

while(ch>='0'&&ch<='9')

return x*w;

}struct node

node(int nx,int ny,int nz)

bool operator == (const node &bb) const

}s1[50],s2[20];

int d1[50],d2[50],t1,t2,ans;

node getfa(node aa)

puts("yes");

while(s1[t1-1]==s2[t2-1])

--t1,--t2;

if(t1&&t2)

else if(s1[t1].z==s2[t2].z)

}printf("%d\n",ans);

return 0;

}

P1852 國家集訓隊 跳跳棋

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

luogu P1505 國家集訓隊 旅遊

題面傳送門 第一次一遍過國集紫題。好激動。一看就是樹剖,只不過操作有點多。把每條邊的權值放在兒子節點即可。對於取相反數放懶標記即可。其他是樹剖正常操作。實現 include include define max a,b a b a b define min a,b a b a b using nam...

Luogu P2839 國家集訓隊 middle

首先 b,c 是必選的,然後選一段 a,b 的字尾和一段 c,d 的字首 都可空 對於中位數 這裡中位數採用這道題的定義 有個常見的處理方式 二分 mid,將 0,則說明 mid 的佔到了一半以上,即中位數 mid。採用這種處理方式,二分中位數,由於要中位數盡量大,所以要貪心,選字尾和字首使得大於等...