codeforces1098D Eels

本文探讨了一种涉及鱼缸中鱼相互吞噬直至只剩一条的算法问题,通过将鱼按质量排序并划分区间,实现对危险吞噬次数的有效计算。文章详细介绍了如何维护区间和以及在O(30)的时间复杂度内进行暴力计算的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面

题意

在鱼缸中有一些鱼,这些鱼之间会相互吞噬直到只剩下一条鱼,若一条鱼的质量为a,另一条鱼的质量为b,则吞噬之后会剩下一条质量为a+b的鱼,若 a &lt; = b a&lt;=b a<=b b &lt; = 2 ∗ a b&lt;=2*a b<=2a,则这次吞噬是危险的。
现在有一个空鱼缸,进行多次操作,每次操作会加入一条鱼或去掉某一条鱼,问这次操作后,鱼缸中的鱼相互吞噬直到只剩下一条鱼,至多有几次是危险的。

做法

首先考虑怎样吞噬才会使危险次数最多,可以发现如果每次挑选最轻的两条鱼互吞,答案最大,进一步可以发现,对所有鱼按质量进行排序后,若一条鱼与其他鱼合并会对答案造成贡献,当且仅当 w i &lt; = 2 ∗ ∑ j &lt; i w j w_i&lt;=2*\sum_{j&lt;i}{w_j} wi<=2j<iwj
现在考虑维护这个东西。
根据鱼的质量将其分为30个区间: [ 1 , 2 ) , [ 2 , 4 ) , [ 4 , 8 ) . . . . . . [ 2 29 , 2 30 ) [1,2),[2,4),[4,8)......[2^{29},2^{30}) [1,2),[2,4),[4,8)......[229,230)
然后可以发现,如果一个区间中有多个元素,则只有最小的元素可能不是危险的,因此我们只要维护每个区间的和,每次询问 O ( 30 ) O(30) O(30)暴力计算即可

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll Q,ans,sum[40];
char str[2];
multiset<ll>num[40];

int main()
{
    ll i,j,t,qz;
    cin>>Q;
    while(Q--)
    {
	scanf("%s%lld",str,&t);
	for(i=1;(1 << i)<=t;i++);i--;
	if(str[0]=='+')
	{
	    sum[i]+=t;
	    num[i].insert(t);
	}
	else
	{
	    sum[i]-=t;
	    num[i].erase(num[i].find(t));
	}
	qz=ans=0;
	for(i=0;i<30;i++)
	{
	    if(!num[i].size()) continue;
	    ans+=(num[i].size()-((*num[i].begin())>2*qz));
	    qz+=sum[i];
	}
	printf("%lld\n",ans);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值