長鏈剖分優化樹形dp

2021-09-23 01:57:31 字數 1308 閱讀 1147

apio鐵牌告辭(開場想打暴力然後gedit碼**5個小時沒寫完三題最低檔暴力真是快樂),聽課也就學到了一丟丟這個東西。

模板題:

首先k級兄弟可以一遍dfs的時候丟到k級父親上變成求k級孩子的詢問。

求k級孩子有個很簡單的做法,直接dfs的時候維護掃到某個點時記錄下的每種dep出現次數,對於所有求這個點k級孩子的詢問減去當前出現次數,dfs完這棵樹後在加上當前出現次數即可。複雜度o(n)。

**:#includeusing namespace std;

const int n=1e6+100;

templatevoid rd(t &x)

templatevoid print(t x)

static int buf[30],bnum;

bnum=0;

while(x)buf[++bnum]=x%10,x/=10;

for(int i=bnum;i>=1;i--)putchar(buf[i]+'0');

}struct pii;

pii(int fi,int sc):fi(fi),sc(sc){};

};int n,q,fa[n],ans[n],stk[n],snum=0,cnt[n],dep[n];

vectorson[n];

vectorq[n];

void dfs(int x)

templatevoid print(t x)

static int buf[30],bnum;

bnum=0;

while(x)buf[++bnum]=x%10,x/=10;

for(int i=bnum;i>=1;i--)putchar(buf[i]+'0');

}struct pii;

pii(int fi,int sc):fi(fi),sc(sc){};

};int n,q,ans[n],stk[n],snum=0,mxd[n],lson[n],*f[n],*mem;

vectorq[n];

int hd[n],nxt[n],to[n],tot=0;

void add(int x,int y)

void dfs(int x)

{ stk[++snum]=x,lson[x]=0,mxd[x]=1;

for(int i=0,v;i這種依靠長鏈剖分優化樹形dp的做法還可以改一改在一些自頂向上傳遞資訊的樹上問題使用,具體做法就是對於當前點子樹內長鏈的那個長兒子,直接把字樹內其它短鏈資訊丟給它,根據之前證明是o(n)的。對於短鏈,則用當前子樹資訊減去這條短鏈裡的資訊,發現與之前幾乎一樣也是o(n),總複雜度就是o(n)的了。(具體題目還沒寫過,瞎bb)

長鏈剖分優化樹上dp

長鏈剖分可以把維護子樹中只與深度有關的資訊做到線性的時間複雜度。例題cf1009f 給一棵樹,定義每個點的dom值為,以該點為根的子樹重中,節點數最多的那一層的層數,即那一層距離這個根節點有幾條邊,如果多層節點數相同,取最小的層數。例如單獨葉節點的dom值是0,一條垂直的鏈的dom值也是0 每層數量...

長鏈剖分隨想

之前寫了那麼長一篇blog 現在不如寫篇小短文 說一下另一種樹鏈剖分方法 長鏈剖分的事情。它可以比重鏈剖分更快地完成一些東西。樹鏈剖分的原始版本重鏈剖分非常經典,這裡就不從頭介紹了。原本的剖分方法是按照子樹大小剖分,與子樹點數最多的兒子連成鏈,所以叫做重鏈剖分 然後顯然就有乙個點到根的路徑上至多 o...

長鏈剖分隨想

之前寫了那麼長一篇blog 現在不如寫篇小短文 說一下另一種樹鏈剖分方法 長鏈剖分的事情。它可以比重鏈剖分更快地完成一些東西。樹鏈剖分的原始版本重鏈剖分非常經典,這裡就不從頭介紹了。原本的剖分方法是按照子樹大小剖分,與子樹點數最多的兒子連成鏈,所以叫做重鏈剖分 然後顯然就有乙個點到根的路徑上至多 o...