U41492 數顏色 樹上啟發式合併

2021-09-26 09:39:39 字數 1237 閱讀 5416

樹上啟發式合併的經典問題。

首先離線處理答案。用乙個顏色陣列記錄某種顏色是否存在過,然後由於不同子樹統計答案的時候互不影響,我們枚舉子樹的時候要清空之前的陣列,但是這就帶來了乙個問題,我們無法向上合併答案了。

啟發式合併的做法是我們先考慮樹剖預處理,然後對於統計乙個結點的答案,先暴力遞迴所有輕兒子的答案不保留陣列,然後遞迴重兒子並且保留陣列,然後再次遞迴所有的輕兒子這次也保留陣列,從而向上更新答案。

由於輕邊的個數不超過o(l

og(n

))

o(log(n))

o(log(

n)),因此每個結點最多向上暴力合併log

loglo

g次,而重鏈的個數也不會超過o(l

og(n

))

o(log(n))

o(log(

n))個,因此複雜度不會超過o(l

ogn)

o(logn)

o(logn

)。

#includeusing namespace std;

typedef long long ll;

const int inf=0x3f3f3f3f;

const ll inf=long_long_max;

const int n=1e5+7;

vectorg[n];

int sz[n],son[n],res[n];

bool check[n];

int c[n];

void dfs1(int u,int fa)

} int dfs2(int u,int fa,int keep)

} int ans=0;

if(son[u]) ans+=dfs2(son[u],u,keep);

for(auto &v:g[u])

if(!check[c[u]])

// keep 1 輕邊不保留check

// keep 0 保留check

if(keep)

return ans;

} int main()

for(int i=1;i<=n;i++)

scanf("%d",&c[i]);

dfs1(1,0);

dfs2(1,0,1);

int q;

scanf("%d",&q);

while(q--)

return 0;

}

U41492 樹上數顏色 dsu

輸入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 表示節...

如何 確定顏色數

可以使用getdevicecaps api呼叫此簡單函式來確定顯示器的顏色 深度 private declare function getdevicecaps lib gdi32 byval hdc as long,byval nindex as long as long function devi...

2017 9 18 數顏色 思考記錄

這個題暴力是不是可以過啊,感覺卡卡常數問題不大 做這個題需要主席樹套樹狀陣列或帶改莫隊,處於經濟考慮,於是學了帶改莫隊 其實差不多,主體和普通莫隊基本一樣,就是多了對修改的暴力處理 把修改次數作為第三關鍵字,放到sort裡就好了 碼 include include include includeus...