Code Forces 496 E. Distributing Parts(贪心)

来源:互联网 发布:Java swing主题大全 编辑:程序博客网 时间:2024/06/05 04:18

Description
有n首曲子,每首曲子的范围为ai~bi。有m个演奏家,每个演奏家的范围为ci~di,并且可以出演次数为ki次。如果ci<= ai<=bi<=di,则说明该曲子可以由演奏家演出。问是否存在合法方案使得所有曲子都能被演奏
Input
第一行为一个整数表示曲子的数量n,之后n行每行两个整数ai和bi表示这首曲子占的时间范围,然后为一整数m表示演奏家人数,之后m行每行三个整数ci,di和ki分别表示演奏家演奏的时间和出演次数
Output
如果存在合法方案使得所有曲子都可以被演奏完毕则输出YES并输出每首曲子分别由哪位演奏家演奏(输出一种可能情况即可),否则输出NO
Sample Input
3
1 3
2 4
3 5
2
1 4 2
2 5 1
Sample Output
YES
1 1 2
Solution
将所有时间段放在同一个结构数组里按结束点升序排序,开一个set记录曲子,枚举结构体中的元素,如果这个时间段是演奏家的演奏阶段,那么set中存放的曲子结束时间显然都小于等于开始时间,一直二分找到开始时间最早的曲子(贪心的让当前演奏家演奏开始时间尽可能早的曲子)让这个演奏家演奏,然后从set中删去这首曲子,直到没有合适的曲子可以演奏或者这个演奏家的演奏次数用完为止;如果这个时间段是曲子的被演奏阶段,那么将这首曲子加入set即可,最后判断被演奏曲子的数量是否为n即可判断是否存在合法方案
Code

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<set> using namespace std;#define maxn 111111int n,m,pf[maxn];struct node{    int l,r,num,op,id;    //op表示是曲子还是演奏家    //如果op=1说明是演奏家,l,r,num就表示其ci,di和ki,id表示其编号    //如果op=0说明是曲子,l,r就表示其ai,bi,id表示其编号 }a[2*maxn];struct edge{    int l,id;    bool operator<(const edge&e)const    {        if(e.l!=l) return e.l>l;        return e.id>id;     }    edge(int a=0,int b=0):id(a),l(b){}}del;set<edge>s;set<edge>::iterator p;bool cmp(node x,node y){    if(x.r!=y.r)return x.r<y.r;    if(x.op!=y.op)return x.op<y.op;    return x.l<y.l;}int main(){    while(~scanf("%d",&n))    {        memset(pf,0,sizeof(pf));//第i首曲子是由第pf[i]个演奏家演奏的         for(int i=1;i<=n;i++)        {            scanf("%d%d",&a[i].l,&a[i].r);            a[i].op=0;a[i].id=i;        }        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            scanf("%d%d%d",&a[i+n].l,&a[i+n].r,&a[i+n].num);            a[i+n].op=1;a[i+n].id=i;        }        sort(a+1,a+n+m+1,cmp);//将这n+m个时间段按结束点排序,那么靠前的一定是结束时间早的         s.clear();        int ans=0;//ans记录能够被演奏的曲子数目         for(int i=1;i<=n+m;i++)            if(a[i].op)            {                while(s.size()&&a[i].num--)                {                    p=s.lower_bound(edge(0,a[i].l));//找到开始时间大于等于a[i].l的曲子中开始时间最小的                     if(p==s.end())break;                    del=*p;                     s.erase(p);//删掉这首曲子                    pf[del.id]=a[i].id;//记录这首曲子的演奏者                     ans++;//被演奏完成的曲子数量加一                 }            }            else                s.insert(edge(a[i].id,a[i].l));        if(ans==n)//所有曲子均被演奏完成则说明存在合法方案         {            printf("YES\n");            for(int i=1;i<=n;i++)                   printf("%d%c",pf[i],i==n?'\n':' ');        }        else printf("NO\n");    }    return 0;}
0 0
原创粉丝点击