https://codeforces.com/contest/1398/problem/E
设当前有cnt个光之符卡
维护3个set,c表示最大的cnt个符卡,f1表示不是c中的剩下的火卡,l1表示不是c中的剩下的光卡
那么答案就是c中的所有卡的值*2+剩下的卡的值,sum为所有卡的值,sum1位c中卡的值,ans=sum+sum1
接下来我们就只需要维护c中总是所有卡中最大的cnt个就行了,当前szc!=cnt都判断一下,然后如果剩下的卡中有比c最小的卡大的就替换一下
注意特判特殊情况,维护一个cntc,表示c中有多少个光之符卡,如果cntc==cnt的话,也就是c中全是光之符卡,那必有一个无法*2,把最小的去掉然后加上剩下的火卡中最大的就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=2e5+10;
int n,cnt;ll ans,sum,sum1;
struct spell
{
int val,tp,id;
bool operator < (const spell &b)const
{
if(val==b.val)
{
if(tp==b.tp)
return id<b.id;
return tp<b.tp;
}
return val<b.val;
}
bool operator == (const spell &b)const
{
return id==b.id;
}
bool operator > (const spell &b)const
{
if(val==b.val)
{
if(tp==b.tp)
return id>b.id;
return tp>b.tp;
}
return val>b.val;
}
}a[maxl];
set<spell> f1,l1,c;
set<spell> :: iterator it;
inline void prework()
{
scanf("%d",&n);
}
inline void mainwork()
{
sum=0;ans=0;sum1=0;cnt=0;
int szc=0,cntc=0,fmx,lmx;
spell d;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].tp,&a[i].val);
a[i].id=i;
if(a[i].val>0)
{
sum+=a[i].val;
if(a[i].tp==0)
f1.insert(a[i]);
else
{
l1.insert(a[i]);
++cnt;
}
}
else
{
if(a[i].tp==0)
{
sum+=a[i].val;
it=c.lower_bound({-a[i].val,0,0});
if(it!=c.end() && (*it).val==-a[i].val && (*it).tp==0)
sum1+=a[i].val,c.erase(it),szc--;
else
f1.erase(f1.lower_bound({-a[i].val,0,0}));
}
else
{
--cnt;sum+=a[i].val;
it=c.lower_bound({-a[i].val,1,0});
if(it!=c.end() && (*it).val==-a[i].val && (*it).tp==1)
sum1+=a[i].val,c.erase(it),szc--,cntc--;
else
l1.erase(l1.lower_bound({-a[i].val,1,0}));
}
}
while(szc<cnt)
{
if(f1.begin()==f1.end())
{
it=l1.end();--it;c.insert(*it);
sum1+=(*it).val;szc++;cntc++;
l1.erase(it);
}
else if(l1.begin()==l1.end())
{
it=f1.end();--it;c.insert(*it);
sum1+=(*it).val;szc++;
f1.erase(it);
}
else
{
if((*f1.rbegin()).val>=(*l1.rbegin()).val)
{
it=f1.end();--it;c.insert(*it);
sum1+=(*it).val;szc++;
f1.erase(it);
}
else
{
it=l1.end();--it;c.insert(*it);
sum1+=(*it).val;szc++;cntc++;
l1.erase(it);
}
}
}
while(szc>cnt)
{
d=(*c.begin());sum1-=d.val;
if(d.tp==0)
f1.insert(d);
else
l1.insert(d),--cntc;
szc--;c.erase(c.begin());
}
while(cnt>0)
{
fmx=0;lmx=0;
if(f1.begin()!=f1.end())
fmx=(*f1.rbegin()).val;
if(l1.begin()!=l1.end())
lmx=(*l1.rbegin()).val;
d=*c.begin();
if(max(fmx,lmx)<=d.val)
break;
sum1-=d.val;c.erase(c.begin());
if(d.tp==1) cntc--;
if(fmx>lmx)
{
sum1+=fmx;it=f1.end();--it;
c.insert(*it);f1.erase(it);
}
else
{
sum1+=lmx;it=l1.end();--it;++cntc;
c.insert(*it);l1.erase(it);
}
if(d.tp==0)
f1.insert(d);
else
l1.insert(d);
}
if(cnt>0 && cnt==cntc)
{
ans=sum1+sum-(*c.begin()).val;
if(f1.begin()!=f1.end())
ans+=(*f1.rbegin()).val;
}
else
ans=sum1+sum;
printf("%lld\n",ans);
}
}
int main()
{
prework();
mainwork();
}