小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 次。刪去重心後任意同一聯通塊中的兩點不構成路...