acm-(模拟、set)Educational Codeforces Round 93 (Rated for Div. 2) Two Types of Spells

题面
传送门
首先如果有 x x x个1类型技能,那么意味着最多可以提供 x x x个位置,这 x x x个位置可以任意选择某种已存在的技能值,并使之扩大两倍。因此考虑用一个集合 a a a维护这些扩大两倍的技能值,用一个集合 b b b记录其它没有被扩大两倍的技能值,再用一个集合 c c c记录1类型技能的值。

有一种特殊情况就是 a a a集合等于 c c c集合的时候,这时候其实1类型技能不可能给自己提供两倍的buff,因此这时候要特判。

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


typedef long long ll;
struct Node{
    set<int>s;
    ll sum=0;
    bool empty(){
        return s.empty();
    }
    int max(){
        if(empty())return 0;
        return *s.rbegin();
    }
    int min(){
        if(empty())return 0;
        return *s.begin();
    }
    void delmin(){
        if(empty())return;
        sum-=min();
        s.erase(s.begin());
    }
    void delmax(){
        if(empty())return;
        sum-=max();
        s.erase(s.find(max()));
    }
    void del(int x){
        if(empty())return;
        sum-=x;
        s.erase(s.find(x));
    }
    bool exist(int x){
        if(empty())return false;
        return s.find(x)!=s.end();
    }
    void add(int x){
        sum+=x;
        s.insert(x);
    }
    int sz(){
        return (int)s.size();
    }
}a,b,c;//加倍、非加倍、冰霜

void movx(Node &src,Node &tar,int x){
    src.del(x);
    tar.add(x);
}
void movmin(Node &src,Node &tar){
    int u=src.min();
    src.delmin();
    tar.add(u);
}
void movmax(Node &src,Node &tar){
    int u=src.max();
    src.delmax();
    tar.add(u);
}
void print(Node &a){
    set<int>::iterator it;
    printf("sz:%d   element:",a.sz());
    for(it=a.s.begin();it!=a.s.end();++it){
        printf("%d ",*it);
    }
    puts("");
}
ll getans(){
    ll ans;
    if(!a.empty() && a.min()==c.min()){
        ans=2*a.sum+b.sum;
        ans-=c.min();
        ans+=b.max();
    }else{
        ans=2*a.sum+b.sum;
    }
    return ans;
}
int main(){
    int n;
    scanf("%d",&n);
    ll suma=0,sumb=0;
    while(n--){
        int tp,d;
        scanf("%d%d",&tp,&d);
        if(d>0){
            if(!a.empty() && a.sz()==c.sz() && d>a.min()){
                movmin(a,b);
                a.add(d);
            }else if(a.sz()<c.sz()){
                a.add(d);
            }else{
                b.add(d);
            }
            if(tp){
                c.add(d);
                while(a.sz()<c.sz() && !b.empty()){
                    movmax(b,a);
                }
            }
        }else{
            d=-d;
            if(b.exist(d))b.del(d);
            else a.del(d);
            if(tp)c.del(d);
            while(a.sz()<c.sz() && !b.empty()){
                movmax(b,a);
            }
            while(a.sz()>c.sz()){
                movmin(a,b);
            }
        }
        //print(a);print(b);print(c);
        printf("%lld\n",getans());
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值