樹上啟發式合併的經典問題。
首先離線處理答案。用乙個顏色陣列記錄某種顏色是否存在過,然後由於不同子樹統計答案的時候互不影響,我們枚舉子樹的時候要清空之前的陣列,但是這就帶來了乙個問題,我們無法向上合併答案了。
啟發式合併的做法是我們先考慮樹剖預處理,然後對於統計乙個結點的答案,先暴力遞迴所有輕兒子的答案不保留陣列,然後遞迴重兒子並且保留陣列,然後再次遞迴所有的輕兒子這次也保留陣列,從而向上更新答案。
由於輕邊的個數不超過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...