NOIP訓練營內部試題 數數(樹形DP 倍增)

2021-09-23 20:31:31 字數 2075 閱讀 2198

摘要:

本文清北學堂noip訓練營試題t3試題。

樣例讀入:
4

1 21 3

2 4樣例輸出:

8樣例解釋:

}解析:

樹形dp+倍增

回想倍增法求lca的過程

從大到小列舉k,每次跳2^k步,只要不越界就跳,最後一定能跳到lca

因為跳的都是2的冪次步,所以每跳一步就是二進位制加了乙個1

先預處理fa[i][k],表示點i向上跳2^k 步的祖先節點

設 f[i][j] 表示最後一步跳了2^j步,跳到了點i的答案之和

cnt[i][j] 表示最後一步跳了2^j步,跳到了點i的方案數

因為有了倍增求lca原理的保證,所以只需要考慮跳2的冪次步

設siz[i]表示以i為根的子樹的大小

rt[i]=j 表示 當前點屬於 i的子樹裡,以j為根節點的子樹

假設dfs回溯到x,轉移分兩種:

1、以x為鏈的乙個端點

列舉x向上跳2^k次,則v=fa[x][j]

那麼ans+=siz[v]-siz[rt[v]] ——所有非rt[v]子樹的點,與x的lca都是v,都會有1的貢獻

(類似於點分治中要去除同一子樹內合法的點)

cnt[v][k]++ f[v][k]++

2、x作為倍增過程中的乙個中途點

那麼列舉最後一步跳了2^i 跳到了x

列舉x再往上跳2^j步,則v=fa[x][j]

那麼ans+=(f[x][i]+cnt[x][i])*(siz[v]-siz[rt[v]])

f[x][i] 是原來的答案,在以v做lca時,又會用 (siz[v]-siz[rt[v]])次

cnt[x][i] 是 要再往上跳2^j步,又有乙個1的貢獻

cnt[v][j]+=cnt[x][i] f[v][j]+=f[x][i]+cnt[x][i]

例:1–2--3–4 如果4到1的距離為3,二進位制為11,對答案的貢獻為2

回溯到4的時候,以4為端點會累積3–4 2–4

回溯到3的時候,以3為端點會累積2–3 1–3

回溯到2的時候,以2為端點會累積1–2,以2為中途點會累積1–2--3–4

(4跳21累積到2裡,然後在列舉2為中途點時,最後一步跳了21到2,2再往上跳2^0)

為什麼在列舉3作為中途點的時候,不列舉跳了2^0次方到了3

因為此時3不是中途點,我們是按跳2^k,k是降序跳的

NOIP訓練營內部試題 分糖果

noip訓練營內部試題 分糖果 摘自 清北學堂noip訓練營試題t2 題目 分糖果 分糖果 candy time limit 1000ms memory limit 128mb 題目描述 總共有n顆糖果,有3個小朋友分別叫做l,y,k。每個小朋友想拿到至少k顆糖果,但這三個小朋友有乙個共同的特點 對...

訓練營第四天 二叉樹

一 基礎知識 二叉樹 二叉樹是乙個連通的無環圖,並且每乙個頂點的度不大於3。有根二叉樹還要滿足根結點的度不大於2。有了根結點之後,每個頂點定義了唯一的父結點,和最多2個子結點。然而,沒有足夠的資訊來區分左結點和右結點。如果不考慮連通性,允許圖中有多個連通分量,這樣的結構叫做森林 遍歷 遍歷是對樹的一...

鄧俊輝 演算法訓練營練習 二叉排序樹

先序遍歷 輸出自己 左子樹 右子樹 中序遍歷 輸出左子樹 自己 右子樹 include using namespace std struct node t 10000 root代表根節點 cnt代表二叉樹大小 int root,cnt 建樹 int insert int v,int x t x lc...