2020CCPC(长春) - Strange Memory(树上启发式合并+位运算)
題目大意:給出一棵?n 個(gè)點(diǎn)組成的有根樹,一號(hào)節(jié)點(diǎn)是根節(jié)點(diǎn),現(xiàn)在要求實(shí)現(xiàn) n * n 的公式:
題目分析:樹上啟發(fā)式合并,需要修改部分內(nèi)部實(shí)現(xiàn),如果可以想到樹啟的話,那么應(yīng)該往子樹上去靠攏,當(dāng)每個(gè)點(diǎn)作為子樹的根時(shí),其可以作為 lca 然后去統(tǒng)計(jì)子樹中可以匹配的 ( u , v ) 點(diǎn)對(duì),這個(gè)題目因?yàn)?a[ i ] != 0,換句話說,點(diǎn) u , v , lca( u , v ) 一定是互不相同的三個(gè)點(diǎn),極大程度上簡(jiǎn)化了題目(因?yàn)槿齻€(gè)點(diǎn)的形式一定是一個(gè)分叉的形狀,不可能是鏈狀的),換句話說,當(dāng) lca 確定后,可以枚舉每個(gè)點(diǎn)作為點(diǎn) u,然后去統(tǒng)計(jì)“除了點(diǎn) u 到點(diǎn) lca 的這條路徑上的點(diǎn)之外,以?lca 為根節(jié)點(diǎn)的子樹中,所有 a[ v ] = a[ u ] ^ a[ lca ] 的點(diǎn) v,然后對(duì) v^u 加和”,但如果每個(gè)點(diǎn)都去枚舉的話,那么時(shí)間復(fù)雜度將會(huì)是 n * n 級(jí)別的,又因?yàn)槿绻總€(gè)點(diǎn)都枚舉一遍的話,換句話說對(duì)于一個(gè)有貢獻(xiàn)的 ( u , v ) 點(diǎn)對(duì)來說,點(diǎn) u 和點(diǎn) v 都會(huì)被枚舉一遍從而形成了浪費(fèi)
再考慮樹啟是關(guān)于輕重鏈剖分的,然后訪問輕鏈的次數(shù)是 O( logn ) 級(jí)別的,因此可以只枚舉輕鏈上的點(diǎn)的貢獻(xiàn),然后去尋找滿足條件的點(diǎn)與其匹配即可,這樣時(shí)間復(fù)雜度就下降到了 nlogn,具體實(shí)現(xiàn)就是,對(duì)于某一條輕鏈來說,先維護(hù)其貢獻(xiàn),然后再將其下標(biāo)更新到數(shù)據(jù)結(jié)構(gòu)中維護(hù)
下面講該如何實(shí)現(xiàn),首先上面簡(jiǎn)化的模型已經(jīng)足夠可以完成公式,但本題實(shí)際上是要求記錄下標(biāo)的異或和,比賽時(shí)沒有多想,直接對(duì)每個(gè)權(quán)值維護(hù)了一個(gè)?set,用于記錄當(dāng)前權(quán)值下有多少個(gè)下標(biāo),維護(hù)答案的時(shí)候暴力枚舉即可,本以為時(shí)間復(fù)雜度是 nlog^2n 的,TLE 的原因是因?yàn)?set 的那一層 log,于是想到每次增加和刪除都是連續(xù)的一段,將 set 換成了 vector 便輕松將時(shí)間復(fù)雜度控制到了 nlogn 級(jí)別,交上去也真的 AC 了,賽后和潘學(xué)長(zhǎng)還有zx學(xué)長(zhǎng)討論過后才發(fā)現(xiàn),自己實(shí)際上寫了個(gè)假算法。。因?yàn)槿绻┝θゾS護(hù)下標(biāo)的話,時(shí)間復(fù)雜度其實(shí)是 O( k * n * logn ),這里的 k 是,整棵樹中出現(xiàn)次數(shù)最多的數(shù)字的出現(xiàn)次數(shù),如果整棵樹都是同一個(gè)數(shù)字的話,那么時(shí)間復(fù)雜度將退化成 O( n * n * logn ) 級(jí)別的。。然鵝感謝出題人,卑微菜雞在這里給你磕頭了,咚咚咚,多謝出題人沒有刻意去卡這種數(shù)據(jù),導(dǎo)致在隨機(jī)數(shù)據(jù)下,常數(shù) k 好像很小很小,甚至比 std 跑的還快。。
然后講一下正解吧,因?yàn)槲覀冃枰S護(hù)的是下標(biāo)的異或和,而對(duì)于異或而言,非常重要的一個(gè)性質(zhì)就是,拆位之后每一位都相互獨(dú)立,所以我們不妨對(duì)于下標(biāo)的每一位都單獨(dú)跑一次樹啟,最后將答案加和即可,對(duì)于某一位來說,假設(shè) u == 1,對(duì)于匹配到的 v 來說,只有 v == 0 的位置才具有貢獻(xiàn),對(duì)于 u == 0 而言,同理只有 v == 1 才有貢獻(xiàn),所以類比于上一段的思路,對(duì)于每個(gè)權(quán)值 val 來說,上一段的做法維護(hù)的是一個(gè) vector,里面儲(chǔ)存著 a[ x ] == val 的 x,也就是下標(biāo),而本段的思路是,對(duì)于每個(gè)權(quán)值 val 來說,記錄一下所有下標(biāo),在二進(jìn)制下第 i 位中共出現(xiàn)了多少個(gè) 0 和多少個(gè) 1,只是換了一下實(shí)現(xiàn)思路而已,這樣實(shí)現(xiàn)的時(shí)間復(fù)雜度是嚴(yán)格 O( nlogn * 20 ) 的,20 的意思是需要將下標(biāo)拆成 20 位,因?yàn)?2^20 > 1e6 >= a[ i ]?
代碼:
?
?
總結(jié)
以上是生活随笔為你收集整理的2020CCPC(长春) - Strange Memory(树上启发式合并+位运算)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 洛谷 - P1025 数的划分(计数dp
- 下一篇: 2020CCPC(长春) - Ragdo