簡介:
(聽名字高大上,實際上沒什麼東西……虛樹的題主要難在如何操作虛樹)
給出$k$個關鍵點,我們要建出一棵只包含這些關鍵點和他們$lca$的點數最少的樹,以實現$dp$等操作。
標誌性的資料範圍是$\sum\leq 10^$之類的。
建樹方法:
1.將所有關鍵點按$dfs$序排序。
2.開乙個棧表示根到當前點的虛樹路徑,並把根丟進去。
3.對於每乙個關鍵點$u$:令$lca$為$u$與$s[top]$的最近公共祖先。
若$lca=s[top]$,則把$u$丟進去。
否則,我們需要彈出棧中所有不在根到$u$路徑上的點。
由於關鍵點是按照$dfs$序排序的,那麼棧中所有$dep$大於$dep[lca]$的點都不在這條路徑上。(容易驗證它們一定在$lca$的另外一顆子樹上)
於是一直彈到最後乙個不滿足要求的點,每彈出乙個點之後就在它和棧頂間連一條邊。
由於我們要把$lca$丟進棧裡,所以最後乙個點應當與$lca$連邊,然後彈掉。
最後把$lca$和$u$丟進棧裡。(如果$s[top]=lca$就不用丟$lca$進去了)
4.最後把棧裡所有點彈掉,每彈出乙個點之後就在它和棧頂間連一條邊。
複雜度分析:
每加乙個點最多產生乙個$lca$,那麼虛樹中的總點數是$o(2k)$的。
清空陣列的時候千萬要計算好複雜度。
**(cf613d kingdom and its cities
):
#include#define maxn 200005虛樹#define maxm 500005
#define inf 0x7fffffff
#define ll long long
#define debug(x) cerr<
namespace
std;
int f[maxn][20
],dep[maxn],dfn[maxn],tot;
int hd[maxn],to[maxn<<1],nxt[maxn<<1
],cnt;
intst[maxn],po[maxn],vis[maxn],ans,flag;
vector
vc[maxn];
inline
intread()
inline
bool cmp(int a,int b)
inline
void add(int a,int
b)inline
void addedge(int u,int
v)inline
void dfs(int u,int
fa)inline
int lca(int u,int
v)inline
int solve(int
u) vc[u].clear();
if(vis[u])
else
}}int
main()
int lt=lca(po[i],st[st[0
]]);
while(st[0]>1 && dep[lt]0]-1
]]) add(st[st[
0]-1],st[st[0]]),st[0]--;
if(dep[lt]0]]]) add(lt,st[st[0]]),st[0]--;
if(st[st[0]]!=lt) st[++st[0]]=lt; st[++st[0]]=po[i];
}while(st[0]>1) add(st[st[0]-1],st[st[0]]),st[0]--;
solve(
1),printf("
%d\n
",(flag)?-1
:ans);
for(int i=1;i<=k;i++) vis[po[i]]=0
; }
return0;
}
虛函式知識點總結
一 虛函式的定義 c 中的虛函式時定義在基類中的函式,子類必須對其進行覆蓋。在類中宣告 無函式體的形式叫做宣告 虛函式的格式 virtual void display 二 虛函式的作用 1.定義子類物件,並且可以呼叫物件中未被子類覆蓋的積累函式a同時在a中,又呼叫了已被子類覆蓋的基類函式b。這樣的話...
知識點 劃分樹
劃分樹,類似線段樹,主要用於求解某個區間的第k 大元素 時間複雜度log n 快排本也可以快速找出,但快排會改變原序列,所以每求一次都得恢復序列。建樹 o n logn o nlogn o nlog n 查詢結點 o l ogn o logn o logn poj 2104 題目意思就是,給你n 個...
樹模型知識點
疑問learning to rank之lambdamart的前世今生 gbdt原理 非常重要 決策樹 上 id3 c4.5 cart 及剪枝 資料探勘十大演算法之cart詳解 深入理解gbdt回歸演算法。對gbdt的原理講解的比較清晰,舉的例子也比較好。參考learning to rank之lamb...