日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【十二省联考】春节十二响【贪心】【堆】【启发式合并】

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【十二省联考】春节十二响【贪心】【堆】【启发式合并】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

題意:給一棵nnn個點帶點權的樹,要求把點分成若干部分,有祖孫關系的點不能在同一部分。求每個部分最大值 的和 的最小值。

n≤2×105n \leq 2\times 10^5n2×105

由鏈的部分得到啟發,每個點用一個堆來維護,合并兩個時不斷彈出兩個堆頂并在最后加入較大值直到一個為空。合并完后加入根,最終的和就是答案。

這樣復雜為兩邊的大小之和。

發現合并是把較少的丟到較大的中,可以啟發式合并,即少的取完后丟回較多的。可以用指針實現。

這樣復雜度是O(nlog?n)O(n\log n)O(nlogn)

好像和長鏈剖分本質相同

#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <queue> #include <vector> #define MAXN 200005 using namespace std; inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } typedef long long ll; typedef priority_queue<int> pq; pq *q[MAXN]; int val[MAXN]; vector<int> e[MAXN]; void dfs(int u) {q[u]=new pq;for (int i=0;i<(int)e[u].size();i++){dfs(e[u][i]);if (q[u]->size()<q[e[u][i]]->size()) swap(q[u],q[e[u][i]]);vector<int> tmp;while (!q[e[u][i]]->empty()) tmp.push_back(max(q[u]->top(),q[e[u][i]]->top())),q[u]->pop(),q[e[u][i]]->pop();for (vector<int>::iterator it=tmp.begin();it!=tmp.end();++it) q[u]->push(*it);}q[u]->push(val[u]); } int main() {int n=read();for (int i=1;i<=n;i++) val[i]=read();for (int i=2;i<=n;i++) e[read()].push_back(i);dfs(1);ll ans=0;while (!q[1]->empty()) ans+=q[1]->top(),q[1]->pop();printf("%lld\n",ans);return 0; }

總結

以上是生活随笔為你收集整理的【十二省联考】春节十二响【贪心】【堆】【启发式合并】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。