51nod 猴猴吃蘋果 樹鏈剖分

2022-09-01 09:27:17 字數 2548 閱讀 6258

這道題有dfs

dfs的解法。我真是遇樹就剖絕了。

線段樹記錄每乙個節點到根節點的距離dep

[i]d

ep[i

],每次選取dep

dep最大點x

x的來轉移。然後把roo

troo

t到xx的路徑上所有點p

p的子樹的dep

dep全部減一,因為這個子樹中每乙個點到根的距離都相當於只要到p

p即可。

拿樣例來說

黃色點是樹根,藍色點是dep

=1de

p=1的點,綠色點是dep

=2de

p=2的點。

那麼depd

ep最大並且編號最小的點是0。

我們把roo

troo

t到0的每乙個節點的子樹的dep

dep減一。並輸出0

那麼這棵樹就變成了

同理,此時我們輸出6

然後又變成了

然後明顯3,5順序輸出了。

所以每乙個點的子樹只要剖一次,時間複雜度o(n

log⁡2n

)o(n

log2n)

#include

#include

#include

using

namespace std;

const

int n=

50010

;int n,root,tot,son[n]

,fa[n]

,top[n]

,size[n]

,dep[n]

,id[n]

,rk[n]

,head[n]

;bool flag[n]

;struct edge

e[n*2]

;struct treenode

;struct tree

else

if(tree[x*2]

.maxn

1].maxn)

else

if(tree[x*2]

.maxn==tree[x*2+

1].maxn && tree[x*2]

.pos

1].pos)

else

}void

pushdown

(int x)

}void

build

(int x,

int l,

int r)

int mid=

(l+r)

>>1;

build

(x*2

,l,mid)

;build

(x*2+1

,mid+

1,r)

;pushup

(x);

}void

update

(int x,

int l,

int r)

pushdown

(x);

int mid=

(tree[x]

.l+tree[x]

.r)>>1;

if(r<=mid)

update

(x*2

,l,r)

;else

if(l>mid)

update

(x*2+1

,l,r)

;else

update

(x*2

,l,mid)

,update

(x*2+1

,mid+

1,r)

;pushup

(x);

}}tree;

void

add(

int from,

int to)

void

dfs1

(int x,

int f)}}

void

dfs2

(int x,

int tp)

}int

main()

dep[0]

=-1; tot=0;

dfs1

(root,0)

;dfs2

(root,root)

; tree.

build(1

,1,n);

printf

("%d\n"

,root-1)

; flag[root]=1

;while

(tree.tree[1]

.maxn)

}return0;

}

51nod 猴猴的比賽

h yp erli nk hyperlink hyperl ink d es crip tion description descri ptio n 給定兩棵樹,求在兩棵樹同時滿足u uu是v vv的父親的對數 資料範圍 n 1 05 n leq 10 5 n 105sol utio nsoluti...

11 02 猴猴吃蘋果

走過的點的權值清零,那麼答案是唯一的,而且終點一定會是葉子節點 那麼我們設初始節點為根節點,先遍歷一次樹,把所有葉子節點記錄下來,以及每個點的父節點,按照深度排序 然後讓每個點沿著父親往上跳,每跳一步答案增加1,遇到根節點或者走過的節點就停止 遇到走過的點說明上面的點取過值了 include def...

51nod 猴猴吃香蕉 揹包

猴猴最愛吃香蕉了。每天猴猴出門都會摘很多很多的香蕉,每個香蕉都有乙個甜度,猴猴不一定要把所有的香蕉都吃掉,猴猴每天都有乙個心情值k,猴猴希望當天吃的香蕉滿足這麼乙個條件,這些香蕉的甜度乘積恰好等於k,但是猴猴並不知道有多少種方法,於是猴猴把這個問題交給你。m 1 08 m leq 10 8 m 10...