這道題有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
log2n
)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...