51nod 1389 跳跳樹 倍增

2021-08-10 11:41:27 字數 1403 閱讀 7715

小a與小b在樹上玩乙個遊戲,每一輪遊戲小a與小b在樹上選兩個點,然後小a朝著小b所在的方向移動。神奇的是,這棵樹上每條邊都有乙個長度的,每個點上都有一棵非常高的松樹。小a可以從高處不耗費任何體力跳往相鄰的低處,也可以耗費一點體力,走不超過k的長度的路徑走到某個點然後跳到松樹頂端(不能停在路**)。現在他們進行了q次遊戲,每一次小a所在的位置為xi的頂端,小b所在的位置為yi的頂端。小a想知道最少耗費多少體力能到達小b所在的位置。

1<=n,q<=300000

調死我了。。。

把詢問沿著lca拆成兩條鏈分別處理。

預處理bz[i,j]表示i花費2^j往上跳最多能跳到**。

然後先從x往上跳,跳到乙個位置滿足再跳一步就能到達或跨過lca,然後再討論一下各種情況,再從y開始往上跳即可。

細節超多。。。

#include

#include

#include

#include

#include

using namespace std;

typedef long long ll;

const int n=300005;

int n,k,cnt,last[n],top1[n],top2[n],bz1[n][20],bz2[n][20],fa[n][20],dep[n],h[n],bin[20],stack[20];

ll dis[n];

struct edgee[n*2];

intread()

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

return

x*f;

}void pri(int

x) int top=0;

while (x) stack[++top]=x

%10,x/=10;

while (top) putchar(stack[top]+'0'),top--;

puts("");

}void addedge(int u,int v,int w)

void dfs(int

x) if (top2[x]!=x) bz2[x][0]=bz2[top2[x]][0];

else

for (int i=1;i<=18;i++)

for (int i=last[x];i;i=e[i].next)

}int get_lca(int

x,int

y)int main()

for (int i=1;i<=n;i++) h[i]=read();

dfs(1);

intq=read();

while (q--)

else

if (lca==y)

else

}return

0;}

樹論 倍增 51nod1709 複雜度分析

倍增與位運算有很多共性 這題做法有一點像 線段樹上二分 和 線段樹套二分 的關係。給出一棵n個點的樹 以1號點為根 定義dep i 為點i到根路徑上點的個數。眾所周知,樹上最近公共祖先問題可以用倍增演算法解決。現在我們需要算出這個演算法精確的複雜度。我們定義計算點i和點j最近公共組先的精確複雜度為b...

51nod1462 樹據結構

給一顆以1為根的樹。每個點有兩個權值 vi,ti,一開始全部是零。q次操作 讀入o,u,d o 1 對u到根上所有點的vi d o 2 對u到根上所有點的ti vi d 最後,輸出每個點的ti值 n,q 100000 有50 的資料n,q 10000 注 所有數64位整數不會爆。我們考慮用樹剖來做這...

51nod 1737 樹的重心

思路 樹的重心也叫樹的質心。找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡。考慮每一條邊被統計進答案幾次,若斷開這條邊後樹形成大小為s1 s2的兩個聯通塊則這條邊最多被統計min s1,s2 次。刪去重心後任意同一聯通塊中的兩點不構成路...