codeforces1398E Two Types of Spells

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
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 (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 f1,l1,c;
set :: 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=(*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();
}

 

你可能感兴趣的:(codeforces1398E Two Types of Spells)