cunzai_zsy0531

关注我

CF1398E Two Types of Spells 题解

如果当前有 \(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;
}
posted @ 2022-05-28 15:02  cunzai_zsy0531  阅读(24)  评论(0编辑  收藏  举报