zoukankan      html  css  js  c++  java
  • CF1398E Two Types of Spells(set+贪心)

    主要是思想是对顶堆,将最大的雷电法术的放入加强集合,其他放入普通集合

    之后维护两种法术的集合大小,因为每次操作最多只会将大小与真正的大小差1,因此判断更新即可

    具体注释看代码,细节比较多,主要是注意判断集合是否非空

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    typedef pair<int,pll> plll;
    const int N=1e6+10;
    set<int> light,fire,s,od;
    ll tmp,res;
    //维护四个集合,分别是light法术、fire法术、被加强的法术、没被加强的法术
    void del(int d,int opt){
        d=-d;
        res-=d;
        if(opt==1) light.erase(d);
        else fire.erase(d);
        if(s.count(d))
            tmp-=d,s.erase(d);
        else
            od.erase(d);
    }
    void add(int d,int opt){
        res+=d;
        if(opt==1) light.insert(d);
        else fire.insert(d);
        //当普通的为空,或者当前值大于最大的普通值,就加入加强的集合
        if(od.empty()||d>*prev(od.end()))
            tmp+=d,s.insert(d);
        else
            od.insert(d);
    }
    void maintain(){
        //当被加强的多了,就要删除最小的
        if((int)s.size()>(int)light.size()){
            tmp-=*s.begin();
            od.insert(*s.begin());
            s.erase(s.begin());
        }
        //当小于,就要加上
        if((int)s.size()<(int)light.size()){
            s.insert(*prev(od.end()));
            tmp+=*prev(od.end());
            od.erase(prev(od.end()));
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        int i;
        for(i=1;i<=n;i++){
            int opt;
            int d;
            cin>>opt>>d;//插入或者删除
            if(d<0) del(d,opt);
            else add(d,opt);
            maintain();//维护状态
            if(od.empty()&&s.empty()){
                cout<<0<<endl;
            }
            else if(fire.empty()||(!light.empty()&&*light.begin()>=*prev(fire.end()))){
                //两种情况要特殊讨论
                //对于一般情况都是有light长度的能被加强,但是当全部法术都是light或者最大light长度属于light的话
                //第一种只有light-1的被加强,第二种是非法的,因为必须要存在一个fire被加强
                //因此策略就是最小的light不能double,如果存在fire,取最大的
                ll ans=tmp+res-*light.begin();
                if(fire.size())
                    ans+=*prev(fire.end());
                cout<<ans<<endl;
            }
            else{
                cout<<tmp+res<<endl;
            }
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    vgrant使用简易教程
    php数组常用函数总结
    php面向对象基础知识整理之类中的属性和方法的使用
    apache和nginx的区别
    thinkphp发送邮箱(以thinkphp5作为示例)。
    利用html2canvas将当前网页保存为图片.
    作为一名程序员该如何思考自己的职业人生?
    js常用返回网页顶部几种方法
    如何本地搭建centos7虚拟主机?
    Spark报错
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13549304.html
Copyright © 2011-2022 走看看