U41492 樹上數顏色 dsu

2021-09-28 22:17:20 字數 1539 閱讀 4402

輸入n(1

e5

)n(1e5)

n(1e5)

表示一棵根為1的樹有n

nn個節點

接下來n−1

n-1n−

1行每行u,v

u,vu,

v表示樹邊

接下來一行n

nn個數,c1,

c2,…

,cn(

1≤ci

≤n

)c_1,c_2,\dots,c_n(1\leq c_i\leq n)

c1​,c2

​,…,

cn​(

1≤ci

​≤n)

表示節點顏色

接下來m(m

≤n

)m(m\leq n)

m(m≤n)

個詢問,每個詢問詢問一顆子樹有多少個顏色。

用樹上啟發式合併(dsu)

先重鏈剖分出重兒子。操作

做法很暴力,但是複雜度就是n

log⁡(n

)n\log(n)

nlog(n

)。

#include

using

namespace std;

const

int n=

1e5+9;

int c[n]

,ans[n]

;struct edgee[n<<1]

;int head[n]

,cnt;

int n;

inline

void

add(

int u,

int v)

; head[u]

=cnt++;}

int son[n]

,siz[n]

;void

dfs(

int u,

int fa)

}int he[n]

,nowson,sum;

void

calc

(int u,

int fa,

int val)

}void

dsu(

int u,

int fa,

bool kep)

if(son[u]

)dsu

(son[u]

,u,1

),nowson=son[u]

;calc

(u,fa,1)

;nowson=0;

ans[u]

=sum;if(

!kep)

}int

main()

for(

int i=

1;i<=n;i++

)cin>>c[i]

;dfs(1

,0);

dsu(1,

0,1)

;int m;

cin>>m;

while

(m--

)return0;

}

U41492 數顏色 樹上啟發式合併

樹上啟發式合併的經典問題。首先離線處理答案。用乙個顏色陣列記錄某種顏色是否存在過,然後由於不同子樹統計答案的時候互不影響,我們枚舉子樹的時候要清空之前的陣列,但是這就帶來了乙個問題,我們無法向上合併答案了。啟發式合併的做法是我們先考慮樹剖預處理,然後對於統計乙個結點的答案,先暴力遞迴所有輕兒子的答案...

CSP S 2019 樹上的數(樹上推理)

過了這麼久看看自己要多久才能切這題,發現還是想歪了一次。先考慮暴力的做法。還是貪心的逐位確定,逐位確定判有沒有解,相當於下面的問題 樹上有一些路徑,一條路徑表示要把 x 的數字換到 y 去,問有沒有解。對於一條路徑 p 1 p 2 p m 限制如下 1.p 1 p 2 是 p 1 的所有相鄰邊中時間...

CSP2019 樹上的數

給定乙個大小為 n 的樹,它共有 n 個結點與 n 1 條邊,結點從 1 sim n 編號。初始時每個結點上都有乙個 1 sim n 的數字,且每個 1 sim n 的數字都只在恰好乙個結點上出現。接下來你需要進行恰好 n 1 次刪邊操作,每次操作你需要選一條未被刪去的邊,此時這條邊所連線的兩個結點...