Codeforces Round #570 (Div. 3) G. Candy Box (hard version) (貪心,優先佇列)
阿新 • • 發佈:2020-11-16
-
題意:你有\(n\)個禮物,禮物有自己的種類,你想將它們按種類打包送人,但是打包的禮物數量必須不同(數量,與種類無關),同時,有些禮物你想自己留著,\(0\)表示你不想送人,問你在送出的禮物數量最大的同時,儘可能的使自己喜歡的留下來,輸出能送出的最大禮物數,以及這些禮物中自己不喜歡的數目.
-
題解:首先,我們肯定要讓送出的禮物數最大,同時喜歡的最小,也就是送的禮物中,儘量讓它的\(f\)是\(1\).這題考慮貪心,我們可以先對禮物數量進行排序,禮物數量相同讓\(1\)多的排在前面,全部丟進優先佇列裡,用\(cur\)記錄當前選的禮物數量,如果\(cur\)等於當前優先佇列裡拿出來的數量,由於\(cur\)
-
程式碼:
struct misaka{ int a; int f; bool operator < (const misaka & mikoto) const { if(a==mikoto.a) return f<mikoto.f; return a<mikoto.a; } }e; int t; int n; map<int,int> mp1,mp2; priority_queue<misaka,vector<misaka>> h; int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>t; while(t--){ cin>>n; int ans1=0; int ans2=0; mp1.clear(); mp2.clear(); rep(i,1,n){ int x,f; cin>>x>>f; mp1[x]++; mp2[x]+=f; } for(auto w : mp1){ e={w.se,mp2[w.fi]}; h.push(e); } int cur=-1; while(!h.empty() && cur!=0){ misaka tmp=h.top(); h.pop(); int val=tmp.a; int f=tmp.f; if(cur!=val){ ans1+=val; ans2+=f; cur=val; } else{ if(val==f){ val--; f--; } else val--; h.push({val,f}); } } while(!h.empty()) h.pop(); cout<<ans1<<' '<<ans2<<'\n'; } return 0; }