传送门
首先如果有
x
x
x个1类型技能,那么意味着最多可以提供
x
x
x个位置,这
x
x
x个位置可以任意选择某种已存在的技能值,并使之扩大两倍。因此考虑用一个集合
a
a
a维护这些扩大两倍的技能值,用一个集合
b
b
b记录其它没有被扩大两倍的技能值,再用一个集合
c
c
c记录1类型技能的值。
有一种特殊情况就是 a a a集合等于 c c c集合的时候,这时候其实1类型技能不可能给自己提供两倍的buff,因此这时候要特判。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node{
set<int>s;
ll sum=0;
bool empty(){
return s.empty();
}
int max(){
if(empty())return 0;
return *s.rbegin();
}
int min(){
if(empty())return 0;
return *s.begin();
}
void delmin(){
if(empty())return;
sum-=min();
s.erase(s.begin());
}
void delmax(){
if(empty())return;
sum-=max();
s.erase(s.find(max()));
}
void del(int x){
if(empty())return;
sum-=x;
s.erase(s.find(x));
}
bool exist(int x){
if(empty())return false;
return s.find(x)!=s.end();
}
void add(int x){
sum+=x;
s.insert(x);
}
int sz(){
return (int)s.size();
}
}a,b,c;//加倍、非加倍、冰霜
void movx(Node &src,Node &tar,int x){
src.del(x);
tar.add(x);
}
void movmin(Node &src,Node &tar){
int u=src.min();
src.delmin();
tar.add(u);
}
void movmax(Node &src,Node &tar){
int u=src.max();
src.delmax();
tar.add(u);
}
void print(Node &a){
set<int>::iterator it;
printf("sz:%d element:",a.sz());
for(it=a.s.begin();it!=a.s.end();++it){
printf("%d ",*it);
}
puts("");
}
ll getans(){
ll ans;
if(!a.empty() && a.min()==c.min()){
ans=2*a.sum+b.sum;
ans-=c.min();
ans+=b.max();
}else{
ans=2*a.sum+b.sum;
}
return ans;
}
int main(){
int n;
scanf("%d",&n);
ll suma=0,sumb=0;
while(n--){
int tp,d;
scanf("%d%d",&tp,&d);
if(d>0){
if(!a.empty() && a.sz()==c.sz() && d>a.min()){
movmin(a,b);
a.add(d);
}else if(a.sz()<c.sz()){
a.add(d);
}else{
b.add(d);
}
if(tp){
c.add(d);
while(a.sz()<c.sz() && !b.empty()){
movmax(b,a);
}
}
}else{
d=-d;
if(b.exist(d))b.del(d);
else a.del(d);
if(tp)c.del(d);
while(a.sz()<c.sz() && !b.empty()){
movmax(b,a);
}
while(a.sz()>c.sz()){
movmin(a,b);
}
}
//print(a);print(b);print(c);
printf("%lld\n",getans());
}
}