• Codeforces Round #386 (Div. 2) 746F(set的运用)


    题目大意

    给出一个歌单(有n首歌),每个歌都有愉悦值和时间,你可以选择从第x首歌开始听(也就是选择连续的一段),并且你可以选择w首歌让它的时间减半,限制时间为k,求最大的愉悦值

    首先我们需要贪心一下,假如从第x首歌开始听,那么要想获得最大的愉悦值,就必须把那些时间最长的歌进行减半处理。

    根据这个,我们就需要利用数据结构来进行维护

    考虑使用两个set来维护,S1中保存没有被减半的歌曲,S2中保存减半了的歌曲

    首先从x=1开始听,每新加进来一首歌i,进行如下处理

    1、S2中还没有w首歌,就直接放进S2里

    2、S2中已经有了w首歌,那么就抽出其中时间最短的歌与i比较,如果i的时间大,就把那个最短的歌放到S1中,把i放到S2中;否则就把i放到S1中

    假如无法放入歌曲,那么就统计出来当前的愉悦值,然后把第一首歌删掉

    删除时要注意,如果删掉的元素在S1中就不需要额外处理,如果在S2中,就要把S1中最长的歌再放到S2中

    然后直到最后一首歌被抽出,输出最大的答案

    每首歌只会被放入或抽出1次,所以复杂度是nlogn

    #include <iostream>
    #include <cstdio>
    #include <set>
    using namespace std;
    const int maxn = 2*111111;
    struct Data
    {
        int t, id;
        Data() {}
        Data(int _t, int _id) { t = _t; id = _id; }
        bool operator <(const Data& B) const
        { return (t == B.t) ? (id < B.id) : t < B.t; }
        bool operator == (const Data& B) const
        { return t == B.t && id == B.id; }
    };
    struct node
    {
        int t, v;
    }a[maxn];
    set<Data> S1, S2;
    int nowt = 0, tot = -1, st = 0;
    void Insert(int ty, int t, int id)
    {
        if(ty == 1)
        {
            S1.insert(Data(t, id));
            nowt += t;
        } else
        {
            S2.insert(Data(t, id));
            nowt += ((t-1)/2+1);
        }
    }
    
    void Erase(int ty, int t, int id)
    {
        if(ty == 1)
        {
            S1.erase(Data(t, id));
            nowt -= t;
        } else
        {
            S2.erase(Data(t, id));
            nowt -= ((t-1)/2+1);
        }
    }
    
    void ERASE(int st)
    {
        if(S1.find(Data(a[st].t, st)) != S1.end()) Erase(1, a[st].t, st);
            else
            {
                Erase(2, a[st].t, st);
                if(S1.size() > 0)
                {
                    Data tmp = *(--S1.end());
                    Erase(1, tmp.t, tmp.id);
                    Insert(2, tmp.t, tmp.id);
                }
            }
    }
    
    int n, w, k;
    int main()
    {
        cin>>n>>w>>k;
        for(int i = 0; i < n; i++) cin>>a[i].v;
        for(int i = 0; i < n; i++) cin>>a[i].t;
        int ans = 0, ANS = 0;
        while(st != n)
        {
            while(nowt <= k)
            {
                tot++;
                if(tot >= n) break;
                if(S2.size() < w)
                {
                    Insert(2, a[tot].t, tot);
                }
                else
                {
                    Data tmp = *S2.begin();
                    if(tmp.t < a[tot].t)
                    {
                        Erase(2, tmp.t, tmp.id);
                        Insert(1, tmp.t, tmp.id);
                        Insert(2, a[tot].t, tot);
                    } else
                    Insert(1, a[tot].t, tot);
                }
                if(nowt <= k)  ans += a[tot].v;
                else
                {
                    ERASE(tot);
                    tot--;
                    break;
                }
                ANS = max(ANS, ans);
            }
            ERASE(st);
            ans -= a[st].v;
            st++;
        }
        cout<<ANS<<endl;
    }
  • 相关阅读:
    elipse图标注解
    Thrift源码解析--transport
    IDL和生成代码分析
    thrift概述
    less分页阅读
    this与super使用总结(java)
    more分页阅读
    Arrays
    Teigha克隆db的blockTableRecord里面的一个实体
    Teigha的BlockTableRecord获取方法
  • 原文地址:https://www.cnblogs.com/Saurus/p/6203015.html
Copyright © 2020-2023  润新知