CF1398E Two Types of Spells 題解
阿新 • • 發佈:2022-05-28
如果當前有 \(sum\) 個可以翻倍,那麼考慮可不可以讓前 \(sum\) 大的都翻倍。可以當且僅當這 \(sum\) 大的數不全能翻倍下一個數。如果全都能翻倍下一個數,那隻能犧牲第 \(sum\) 大的數,最後可以再翻倍一個第 \(sum+1\) 大的。
然後有多次刪除插入就用 set
維護一下就行了。
點選檢視程式碼
std::set<int> t[2],is; int n,cnt[2]; ll sum[2]; inline void update(int id){ int x=(id?*t[id].begin():*t[id].rbegin()); bool op=is.count(x); sum[id]-=x,sum[id^1]+=x; t[id].erase(x),t[id^1].insert(x); cnt[id]-=op,cnt[id^1]+=op; } int main(){ //file(); read(n); while(n--){ int op,x;read(op),read(x); if(x>0){ sum[0]+=x; t[0].insert(x); cnt[0]+=op; if(op) is.insert(x); } else{ x=-x; int id=(t[1].count(x)); sum[id]-=x;t[id].erase(x);cnt[id]-=op; if(op) is.erase(x); } int tot=cnt[0]+cnt[1]; while(t[1].size()<tot) update(0); while(t[1].size()>tot) update(1); while(!t[0].empty()&&!t[1].empty()&&*t[0].rbegin()>*t[1].begin()) update(0),update(1); ll ans=sum[0]+2*sum[1]; if(tot&&cnt[1]==tot){ ans-=*t[1].begin(); if(!t[0].empty()) ans+=*t[0].rbegin(); } println(ans); } return 0; }