码迷,mamicode.com
首页 > 其他好文 > 详细

2016暑假集训补题系列

时间:2016-08-16 23:43:40      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

Codefoeces 496E(贪心+二分)

题意:一场演出有N段演奏,每段演奏都有一个音域,有M个演唱家,每个演唱家也分别有自己的音域,而且同一场演出中能演唱最多K次。问是否能够使所有的演奏都能进行,如果能应该怎样分配演唱顺序。

思路:先排个序,把每段演奏以及每个人都按照音域[L,R],R小的优先,相同的情况下,L小的优先。然后对每个人依次操作。每次操作把演奏的R小于等同于该演唱者的R的部分放入multiset中(这里要用到其自动排序和可二分查找的功能),然后二分找到集合中刚好满足演奏的L大于等于演唱者L的位置,然后依次往后找知道没有或者该演唱者次数已够。并把这之中的所有元素删除。

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
struct node{
    int l,r,k,pos;
    friend bool operator<(node x,node y){
        return x.l<y.l;
    }
} a[100005],b[100005];
bool cmp(node a,node b){
    if(a.r==b.r) return a.l<b.l;
    return a.r<b.r;
};
int ans[100005],cnt;
int main(){
    int n,m;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
        a[i].pos=i;
    }
    scanf("%d",&m);
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].k);
        b[i].pos=i;
    }
    sort(a,a+n,cmp);
    sort(b,b+m,cmp);
    multiset<node> s;
    int cnt=0,cur=0;
    for(int i=0;i<m;i++){
        while(cur<n&&a[cur].r<=b[i].r){
            s.insert(a[cur]);
            cur++;
        }
        multiset<node>::iterator e,top;
        top=s.lower_bound(b[i]);
        e=s.lower_bound(b[i]);
        int p=0;
        while(!s.empty()&&e!=s.end()&&p<b[i].k){
            node u=*e;
            ans[u.pos]=b[i].pos;
            e++; p++; cnt++;
        }
        s.erase(top,e);
    }
    if(cnt!=n) printf("NO\n");
    else{
        printf("YES\n");
        for(int i=0;i<n;i++)
            printf("%d ",ans[i]+1);
    }

    return 0;
}
Psong

 

2016暑假集训补题系列

标签:

原文地址:http://www.cnblogs.com/N-Psong/p/5778021.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!