虛樹 學習筆記

2021-08-18 08:55:36 字數 2481 閱讀 2643

水平不夠,學習來湊

又開了個天大的新坑…

sdoi 2011 消耗戰

題目大意就是講:給出一棵樹,有邊權,然後給出k個查詢點,問從1號店不能到任何乙個查詢點的代價是多少.

先考慮一下樹形動歸.

dp[i]表示從1不能到以i為根的子樹中的所有查詢點的最小代價

考慮維護乙個量,mins[i]表示從1到i路徑最小權值

dp[i]顯然要通過枚舉子樹轉移

如果i不是葉子的話,那麼dp

[i]=

min(

∑jdp

[j],

mins

[j])

d p[

i]=m

in(∑

jdp[

j],m

ins[

j])j為i的子樹鄰接點

顯然每次得到dp[1]是要花費o(n)的代價的 只有40pts…

如果是上面的樹形dp,那麼總的複雜度就是 o(n*m)

然而題目裡告訴我們∑m

ki<=

500000

∑ ki

m<=

500000

,就要考慮在這下手了

如果我們可以發現,在轉移的時候很多點都是無用的,其實有用的點就只有查詢點和一些他們的lca

那麼我們就可以考慮重新構造出一棵樹,每個節點的維護值與原樹等價,但是深度很低,我們把這個樹稱為虛樹。

虛樹上的點一定是<=2*k的

這樣這題就可做了

首先我們需要乙個單調棧來維護一條從根節點延伸下來的鏈,然後我們有四個節點。

1:當前點

2:棧頂

3:次棧頂

4:lca(當前點,棧頂)

考慮點4,有兩種可能。

1:點4在點3的上方,那麼點3向點2倆邊,點2出棧。

2:點4在點2和點3的中間,那麼點4向點2連邊,點2出棧,點4入棧,鏈底部顯然是點1,所以點1入棧。

於是我們就構造出了一顆虛樹。

假設查詢點為 5、8、10,那麼虛樹大概是長這個樣子

1:求lca樹剖不知道比倍增快到哪去了

2:我們對於每次的查詢重新構造時,並不需要每次都初始化head陣列,而是可以在上次的樹遍歷裡直接初始化(要不t成sb

#include 

#include

#include

#include

#define int long long

const

int maxm=251000;

int head[maxm],to[maxm<<1],net[maxm<<1],cost[maxm<<1];

int son[maxm],siz[maxm],fa[maxm],top[maxm],dfn[maxm],deep[maxm],mins[maxm];

int h[maxm],stk[maxm],tops;

int dp[maxm];

bool vis[maxm];

int tot,cnt;

int n,q;

inline

void addedge(int u,int v,int c)

inline

bool comp(int a,int b)

}void dfs2(int now,int topx)

inline

int lca(int u,int v)

return deep[u]void dfs(int now)

head[now]=0;

dp[now]=ans?std::min(ans,mins[now]):mins[now];

}void buildtree()

addedge(stk[tops-1],stk[tops],0);

tops--;

} if(stk[tops]!=now)stk[++tops]=now;

} while(--tops) addedge(stk[tops],stk[tops+1],0);

dfs(1);

printf("%lld\n",dp[1]);

}main()

mins[1]=1e60;

dfs1(1,0,0),dfs2(1,1);

//for(int i=1;i<=n;i++) printf("%d\n",mins[i]);

memset(head,0,sizeof(head));

scanf("%lld",&q);

while(q--)

buildtree();

return

0;}

暫無…

虛樹學習筆記

將關鍵點按dfs序排序後,所有關鍵點與相鄰關鍵點的lca合起來構成虛樹 通常還要加上整棵樹的根 虛樹至多有2k2k 個點。體現在實現中就是每次都pop若干點,並有機會push2個點。stk中存的是從根到當前點的遞迴棧中目前選入虛樹的點。stk中的點之間都未連邊 因為事實上關係還未確定 pop掉乙個點...

虛樹學習筆記

虛樹常常被使用在樹形 dp 中。有些時候,我們需要計算的節點僅僅是一棵樹中的某幾個節點 這個時候如果對整棵樹都進行一次計算開銷太大了 所以我們需要把這些節點從原樹中抽象出來 按照它們在原樹中的關係重新建一棵樹,這樣的樹就是虛樹 在構建之前,我們需要把所有需要加入的節點按照 dfn 序從小到大排好序 ...

學習筆記 虛樹

模板 樹剖 lca 建虛樹 include using namespace std const int maxn 100000 10 int n,m,dp maxn vis maxn h maxn sta maxn top int fir maxn head maxn to maxn 1 nxt m...