• [CF496E] Distributing Parts


    Description

    (n) 首独奏乐曲,第 (i) 首的音高范围为 ([a_i,b_i]),有 (m) 位演奏家,第 (i) 位能演奏的音高范围为 ([c_i,d_i]),且他最多可以出演 (k_i) 次。问是否存在合法方案能使所有乐曲都被演奏一次。

    Solution

    对于所有乐曲和演奏家,按照左端点排序,从小到大依次扫描

    维护一棵演奏家的平衡树,关键字为 (d_i),同时记录其剩余的出演次数

    扫描中,每遇到新的演奏家,就将其加入平衡树

    每遇到新的乐曲,显然对平衡树中所有的演奏家,一定满足 (c le a),只需要约束 (b le d)

    故在平衡树中二分,找到 (ge b) 的第一位演奏家,将其出演次数 (-1),如果为 (0) 则将其从平衡树中删除

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    const int type_player = 0;
    const int type_song = 1;
    
    int n_song, n_player, n_event;
    
    struct player
    {
        int c,d,k;
        void scan()
        {
            cin>>c>>d>>k;
        }
    } players[N];
    
    struct song
    {
        int a,b;
        void scan()
        {
            cin>>a>>b;
        }
    } songs[N];
    
    struct event
    {
        int type; //0-player 1-song
        player m_player;
        song m_song;
        int id;
        void assign(player _player,int _id)
        {
            type=0;
            m_player=_player;
            id=_id;
        }
        void assign(song _song,int _id)
        {
            type=1;
            m_song=_song;
            id=_id;
        }
        int getkey()
        {
            int ans=0;
            if(type==0) ans=m_player.c*2;
            if(type==1) ans=m_song.a*2;
            if(type==1) ++ans;
            return ans;
        }
        bool operator < (event& obj)
        {
            return getkey() < obj.getkey();
        }
    } events[N];
    
    void read_data()
    {
        cin>>n_song;
        for(int i=1;i<=n_song;i++) songs[i].scan();
        cin>>n_player;
        for(int i=1;i<=n_player;i++) players[i].scan();
    }
    
    void make_events()
    {
        for(int i=1;i<=n_song;i++) events[i].assign(songs[i],i);
        for(int i=1;i<=n_player;i++) events[i+n_song].assign(players[i],i);
        n_event = n_song + n_player;
        sort(events+1, events+n_event+1);
    }
    
    struct node
    {
        int d,k,id;
        bool operator < (const node b) const
        {
            return d < b.d;
        }
        void dec()
        {
            k--;
        }
    };
    
    int rec[N];
    
    void solve()
    {
        multiset <node> s;
    
        for(int i=1;i<=n_event;i++)
        {
            event &now = events[i];
            if(now.type == type_player)
            {
                node tmp = {now.m_player.d, now.m_player.k, now.id};
                s.insert(tmp);
            }
            if(now.type == type_song)
            {
                song &pre = now.m_song;
                multiset <node>::iterator it = s.lower_bound({pre.b});
                if(it==s.end())
                {
                    cout<<"NO";
                    return;
                }
                else
                {
                    rec[now.id] = it->id;
                    if(it->k == 1) s.erase(it);
                    else
                    {
                        node tmp = *it;
                        s.erase(it);
                        tmp.dec();
                        s.insert(tmp);
                    }
                }
            }
        }
    
        cout<<"YES"<<endl;
        for(int i=1;i<=n_song;i++) cout<<rec[i]<<" ";
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        read_data();
        make_events();
        solve();
    }
    
    
  • 相关阅读:
    暑假日报-35
    非确定性有穷状态决策自动机练习题Vol.1 题解 & 总结
    loj数列分块入门 1~9
    第12周作业
    第二阶段考试
    UOJ NOI Round 4
    事件
    爬楼梯
    构造函数输出
    比较版本号大小
  • 原文地址:https://www.cnblogs.com/mollnn/p/13581053.html
Copyright © 2020-2023  润新知