当前位置: 代码迷 >> 综合 >> codeforces1398E.Two Types of Spells
  详细解决方案

codeforces1398E.Two Types of Spells

热度:16   发布时间:2023-11-24 00:27:24.0

题意:两种类型的魔法,一种火魔法造成x点伤害,另一种电魔法造成x点伤害并使后一次魔法造成伤害翻倍,n(2e5)次操作,每次获得或失去一种魔法,求每次能造成的最大伤害.

用small和big两个set记录较小和较大两部分和,其中big大小等于elec大小,每次插入或删除一个数更新big和small两个set,复杂度为logn;k个电魔法可使k或k-1个魔法伤害翻倍,令sum = sumsmall + sumbig + sumbig,即使较大的k个魔法伤害翻倍的结果;当电魔法存在且火魔法为空时,电魔法只能加倍n-1个魔法,当电魔法最小伤害比火魔法最大伤害还要大时,因为电魔法最多能翻倍k-1个点魔法,所以需要加倍的电魔法最小伤害替换为火魔法的最大伤害

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 1;
int n;
int main(){cin>>n;set<int>small,big;set<int>fire, elec;ll sumbig = 0 , sumsmall = 0;for(int i = 0; i < n; ++i) {int x,y;cin>>x>>y;if(y > 0){(x == 0 ? fire : elec).insert(y);if(big.empty() || y < *big.begin()) {small.insert(y);sumsmall += y;}else {big.insert(y);sumbig += y;}}else {y *= -1;(x == 0 ? fire : elec).erase(y);if(big.count(y))big.erase(y), sumbig -= y;else small.erase(y), sumsmall -= y;;if(fire.count(y))fire.erase(y);else elec.erase(y);}while(big.size() > elec.size()) {sumbig -= *big.begin();sumsmall += *big.begin();small.insert(*big.begin());big.erase(big.begin());}while(big.size() < elec.size()) {sumbig += *small.rbegin();sumsmall -= *small.rbegin();big.insert(*small.rbegin());small.erase(*small.rbegin());}ll ans = sumbig + sumbig + sumsmall;if(elec.size() && (fire.empty() || *elec.begin() > *fire.rbegin())) {ans -= *elec.begin();if(!fire.empty()) {ans += *fire.rbegin();				}}cout << ans <<endl;}
}

 

  相关解决方案