これは正答者少な目だけど、自力で解けた。
http://codeforces.com/contest/521/problem/D
問題
初期状態でK個のパラメータA[i]がある。
ここでN個のアイテムがある。各アイテムは種類T[i]・対象パラメータI[i]・値B[i]の3つの要素で構成される。
アイテムは3種類あり、それぞれ以下の効果がある。
- 種類1:A[I[i]]=B[i]にする。
- 種類2:A[I[i]]+=B[i]にする。
- 種類3:A[I[i]]*=B[i]にする。
アイテムは任意の順番で利用できる。
ただし利用できるのは最大M個までである。
全パラメータの積を最大にするには、どの順でアイテムを利用すればよいか。
解法
各パラメータxに関しては、(アイテムの数を無視すれば)以下の順にアイテムを適用するのが良い。
- 種類1のうち最大のB[i]を1回だけ適用する。
- 種類2のうちB[i]が大きい順に適用する。
- 種類3のうちB[i]が大きい順に適用する。
まず種類1・2を考える。
種類2のアイテムをB[i]降順にソートし、種類1がある場合は先頭に最大の(B[i]-A[x])を追加する。
(種類1のアイテムを(B[i]-A[x])増加する種類2のアイテム、と考える)
あとはこれらのアイテムを順に適用したとき、A[i]が何倍になっていくかを考え、その倍率をpriority_queueに突っ込む。(この時倍率はdoubleで計算する)
次に、種類3に相当するものを同様にpriority_queueに突っ込む。
そして最大M個まで、倍率が高い順にpriority_queueから取り出して答える。
その際、倍率が高い順に答えてはだめで、種類1・2・3の順で答える。
int K,N,M; vector<pair<double,int> > V[101000][3]; int A[101000],T[101000]; vector<pair<double,int> > R; void solve() { int i,j,k,l,r,x,y; string s; cin>>K>>N>>M; FOR(i,K) cin>>A[i]; FOR(i,N) { cin>>j>>x>>y; T[i]=j; V[x-1][j-1].push_back(make_pair(y,i)); } FOR(i,K) { vector<pair<double,int> > T; sort(V[i][0].begin(),V[i][0].end()); if(V[i][0].size() && V[i][0].back().first>A[i]) V[i][1].push_back(make_pair(V[i][0].back().first-A[i],V[i][0].back().second)); sort(V[i][1].begin(),V[i][1].end()); reverse(V[i][1].begin(),V[i][1].end()); double cur=A[i]; FOR(j,V[i][1].size()) { T.push_back(make_pair((cur+V[i][1][j].first)/cur,V[i][1][j].second)); cur += V[i][1][j].first; } ITR(it,T) R.push_back(*it); ITR(it,V[i][2]) R.push_back(*it); } sort(R.begin(),R.end()); reverse(R.begin(),R.end()); FOR(i,R.size()) { if(i>=M || R[i].first<1) R.resize(i); } _P("%d\n",R.size()); FOR(i,R.size()) if(T[R[i].second]==1) _P("%d ",R[i].second+1); FOR(i,R.size()) if(T[R[i].second]==2) _P("%d ",R[i].second+1); FOR(i,R.size()) if(T[R[i].second]==3) _P("%d ",R[i].second+1); _P("\n"); }
まとめ
最初倍率順にpriority_queueに突っ込むのはすぐ思いつけた。
ただ種類1・2・3の順に出力するのを間違えた。