CF EducationalRound93 E.Two Types of Spells(权值线段树+堆维护最值)

题意
每个魔法都有自己的伤害,魔法1是加倍魔法,可以加倍后一个魔法的伤害,魔法0是普通魔法,给出q个更新,要求每次更新后计算魔法能造成的伤害最大值。
思路
设加倍魔法数量为k,权值线段树每次查询前k大的伤害和sumk(加倍多出来的伤害),mutiset维护魔法1和魔法2的最值,如果魔法1的最小值比魔法0的最大值大或不存在魔法0,sumk就要改变,因为至多加倍k-1个魔法1。
代码

#include<bits/stdc++.h>
#define ll long long
#define LL long long
#define PB push_back
#define MP make_pair
using namespace std;
const int maxn=4e5+100;
const ll inf=1e18+10;
ll ID[maxn],ni,QT[maxn*4],C[maxn*4];
int n;
struct node{
	ll ty,d;
}q[maxn];
void Unique(){
	sort(ID+1,ID+1+n);
	ni=unique(ID+1,ID+n+1)-ID-1;
}
ll getid(ll x){
	return lower_bound(ID+1,ID+1+ni,x)-ID;
}
void add(ll o,ll l,ll r,ll x,ll v){
	if(l==r){
		QT[o]+=v;
		C[o]+=ID[x]*v;
	}
	else{
		ll mid=(l+r)>>1;
		if(x<=mid) add(o<<1,l,mid,x,v);
		else add((o<<1)|1,mid+1,r,x,v);
		QT[o]=QT[o<<1]+QT[(o<<1)|1];
		C[o]=C[o<<1]+C[(o<<1)|1];
	}
}
 
ll sumk(ll o,ll l,ll r,ll k){
	if(l==r){
		if(k>=QT[o])return C[o];
		else return C[o]/QT[o]*k;
	}
	else{
		ll mid=(l+r)>>1;
		ll sl=QT[o<<1],sr=QT[(o<<1)|1];
		if(k<=sr) return sumk((o<<1)|1,mid+1,r,k);
		else return C[(o<<1)|1]+sumk(o<<1,l,mid,k-sr);
	}
}
 
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld %lld",&q[i].ty,&q[i].d);
		ID[i]=abs(q[i].d);
	}
	Unique();
	int fire=0,light=0;
	multiset<ll,greater<ll>>fireSet;
    multiset<ll,less<ll>>lightSet;
	ll sum=0;
	for(int i=1;i<=n;i++){
		ll val=q[i].d;
		if(val>0)add(1,1,ni,getid(val),1);
		else add(1,1,ni,getid(-val),-1);
		if(q[i].ty){
			if(val>0)lightSet.insert(val),light++;
			else lightSet.erase(-val),light--;
		}
		else{
			if(val>0)fireSet.insert(val),fire++;
			else fireSet.erase(-val),fire--;
		}
		sum+=val;
		ll sumk0=sumk(1,1,ni,light);
		if(light&&fire){
			ll li=*lightSet.begin(),fi=*fireSet.begin();
			if(li>fi)sumk0+=fi-li;
		}
		else if(light&&!fire){
			ll li=*lightSet.begin();
			sumk0-=li;
		}
		printf("%lld\n",sum+sumk0);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我是一名AI语言模型,不能编写代码。但我可以提供一个Java实现的水花仙术的思路供您参考: 1. 创建一个水花仙术类,包含以下属性: - `name`:水花仙术名称 - `level`:水花仙术等级 - `manaCost`:水花仙术所需魔力值 - `effect`:水花仙术效果 2. 创建一个施法者类,包含以下属性: - `name`:施法者名称 - `mana`:施法者当前魔力值 - `maxMana`:施法者最大魔力值 - `spells`:施法者已经学习的水花仙术列表 3. 创建一个施法者类的方法 `castSpell`,实现施法者使用水花仙术的逻辑: - 首先检查施法者是否已经学会了该水花仙术,如果没有,则无法使用; - 然后检查施法者当前魔力值是否足够支付该水花仙术的魔力值消耗,如果不足,则无法使用; - 最后,执行水花仙术的效果,并扣除相应的魔力值消耗。 4. 创建一个测试类,在其中创建一个施法者对象和一些水花仙术对象,并进行测试。 以下是一份伪代码,供您参考: ``` public class WaterMagic { private String name; private int level; private int manaCost; private String effect; // constructor public WaterMagic(String name, int level, int manaCost, String effect) { this.name = name; this.level = level; this.manaCost = manaCost; this.effect = effect; } // getters and setters // ... // Cast the spell public void castSpell() { // Check if the caster knows the spell if (!caster.getSpells().contains(this)) { System.out.println(caster.getName() + " does not know " + this.getName() + "."); return; } // Check if the caster has enough mana to cast the spell if (caster.getMana() < this.getManaCost()) { System.out.println(caster.getName() + " does not have enough mana to cast " + this.getName() + "."); return; } // Cast the spell and deduct the mana cost from the caster's mana System.out.println(caster.getName() + " casts " + this.getName() + " and " + this.getEffect() + "."); caster.setMana(caster.getMana() - this.getManaCost()); } } public class Caster { private String name; private int mana; private int maxMana; private List<WaterMagic> spells; // constructor public Caster(String name, int maxMana) { this.name = name; this.maxMana = maxMana; this.mana = maxMana; this.spells = new ArrayList<>(); } // getters and setters // ... // Learn a new spell public void learnSpell(WaterMagic spell) { this.spells.add(spell); System.out.println(this.getName() + " learns " + spell.getName() + "."); } // Cast a spell public void castSpell(WaterMagic spell) { spell.castSpell(this); } } public class TestWaterMagic { public static void main(String[] args) { // Create a caster Caster caster = new Caster("Alice", 100); // Create some spells WaterMagic spell1 = new WaterMagic("Bubble Blast", 1, 10, "blasts a wave of bubbles at the enemy"); WaterMagic spell2 = new WaterMagic("Water Whip", 2, 20, "whips the enemy with a whip made of water"); WaterMagic spell3 = new WaterMagic("Tsunami", 3, 50, "summons a giant wave to crash into the enemy"); // Have the caster learn the spells caster.learnSpell(spell1); caster.learnSpell(spell2); caster.learnSpell(spell3); // Cast some spells caster.castSpell(spell1); caster.castSpell(spell2); caster.castSpell(spell3); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值