春節十二響
春節十二響
題目背景
「清明時節雨紛紛,路上行人慾斷魂。」
2075 年的清明沒有春雨。在漫天飛雪的籠罩下,穿行在冰原間的,只有載着人類微薄希望的雪地車。
遙遙 4.22 光年的征途,對於地球這孤獨的旅人而言,恐怕也是無比寂寞的吧。
題目描述
距離蘇拉威西只有一百公里了,車內的空氣比窗外更加冰冷。四雙眼睛緊盯着艾莉芬面前的屏幕,那是控制行星發動機的關鍵程序:春節十二響。他需要將其部署到電力控制系統的一個芯片中。
「春節十二響」由 $n$ 個子程序構成,第 $i$ 個子程序所需的內存空間是 $M_i$。這 $n$ 個子程序之間的調用關係構成了一棵以第 $1$ 個子程序爲根的樹,其中第 $i$ 個子程序在調用樹上的父親是第 $f_i$ 個子程序。
由於內存緊張,電力控制芯片上提供了一種內存分段機制。你可以將內存分爲若干個段 $S_1, S_2, \dots, S_k$,並將每個程序預先分配到一個固定的段。如果兩個子程序沒有直接或間接的調用關係,則他們可以被分配到同一個段中,反之則不能。換言之,當且僅當 $a$ 和 $b$ 在調用樹上**不是祖先-後代關係**,$a$ 和 $b$ 可以被分配到同一個段中。
一個段的大小應當是所有分配到這個段的子程序所需內存大小的最大值,所有段大小的和不能超過系統的內存大小。
現在艾莉芬想要知道,電力控制芯片至少要有多少內存,才能保證春節十二響的正確運行。即:最少需要多大的內存,才能通過先**將內存分成若干個段**,再**把每個子程序分配到一個段中**,使得**每個段中分配的所有子程序之間不存在祖先-後代關係**。
sol
可以發現如果分成的段數最少那麼答案最優。
一棵深度爲dep的樹只要要分dep層。
現在考慮怎麼合併兩棵樹:兩個大根堆,每次取較大的堆頂,直到有個堆爲空。
類似啓發式合併。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #define maxn 200005 9 using namespace std; 10 int n,a[maxn],f[maxn],t[maxn],tp; 11 priority_queue<int>q[maxn]; 12 int main(){ 13 cin>>n; 14 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 15 for(int i=2;i<=n;i++)scanf("%d",&f[i]); 16 for(int i=n;i>1;i--){ 17 int x=i,y=f[i]; q[x].push(a[i]); 18 if(q[x].size()>q[y].size())swap(q[x],q[y]); 19 for(tp=0;!q[x].empty();q[x].pop(),q[y].pop())t[++tp]=max(q[x].top(),q[y].top()); 20 for(int j=1;j<=tp;j++)q[y].push(t[j]); 21 22 } 23 long long ans=a[1]; 24 for(;!q[1].empty();q[1].pop())ans+=q[1].top(); 25 cout<<ans<<endl; 26 return 0; 27 }