You are an assistant director in a new musical play. The play consists of n musical parts, each part must be performed by exactly one actor. After the casting the director chose m actors who can take part in the play. Your task is to assign the parts to actors. However, there are several limitations.
First, each actor has a certain voice range and there are some parts that he cannot sing. Formally, there are two integers for each actor,ci and di (ci ≤ di) — the pitch of the lowest and the highest note that the actor can sing. There also are two integers for each part — ajand bj (aj ≤ bj) — the pitch of the lowest and the highest notes that are present in the part. The i-th actor can perform the j-th part if and only if ci ≤ aj ≤ bj ≤ di, i.e. each note of the part is in the actor's voice range.
According to the contract, the i-th actor can perform at most ki parts. Besides, you are allowed not to give any part to some actors (then they take part in crowd scenes).
The rehearsal starts in two hours and you need to do the assignment quickly!
The first line contains a single integer n — the number of parts in the play (1 ≤ n ≤ 105).
Next n lines contain two space-separated integers each, aj and bj — the range of notes for the j-th part (1 ≤ aj ≤ bj ≤ 109).
The next line contains a single integer m — the number of actors (1 ≤ m ≤ 105).
Next m lines contain three space-separated integers each, ci, di and ki — the range of the i-th actor and the number of parts that he can perform (1 ≤ ci ≤ di ≤ 109, 1 ≤ ki ≤ 109).
If there is an assignment that meets all the criteria aboce, print a single word "YES" (without the quotes) in the first line.
In the next line print n space-separated integers. The i-th integer should be the number of the actor who should perform the i-th part. If there are multiple correct assignments, print any of them.
If there is no correct assignment, print a single word "NO" (without the quotes).
3 1 3 2 4 3 5 2 1 4 2 2 5 1
YES 1 1 2
3 1 3 2 4 3 5 2 1 3 2 2 5 1
NO
题意:
有一些歌手和一些曲目,对于每个曲目i都有一个要求(ai,bi),对于每个歌手j都有一个自身能力值(cj,dj,k)k表示最多能选的曲目的个数。
一个歌手j能选择一个曲目i时当且仅当对于(cj<=ai<=bi<=dj)。现在需要一种合适的分配方案,使得每个曲目都被某一个歌手选择。(允许存在某个歌手一个曲目都没有选)。
反思:
与其说是不会写,不如说是自己数据结构太弱造成的。本题对我来说,瓶颈在于:set里面跑lower_bound。 以前都是在线性数组里跑lower_bound。在这道题中,正式地第一次在set(mult)里跑lower_bound。同时也在今后写题的过程中,多了一份新的概念,新的思路。谨记谨记。
希望下次再也不会写这种题的题解了。
分析:
先对歌手以及话剧分别排一次序( if(a.a==b.a)return a.b<b.b;return a.a<b.a;)
维护一个(multi)set,里面存放着当前的歌手。
再对歌手维护一个指针j,话剧维护一个指针i。
对于有序的第i个话剧。我们把下界比它小的歌手全塞进set里。然后再二分查找set中上界不比它小且上界最小的歌手。拿出来,k-=1,放回去。用贪心思想不难感觉出。这样贪无疑是最优的。拿出来的时候别忘了标记,放回去之前别忘了检查这个歌手是否还有机会选择其他话剧(k>0)。
时间复杂度为:O((n+m)*log(n+m))
下面给出代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
using namespace std;
const int maxn=1e5+7;
struct node2
{
int a,b,k,id;
bool operator <(const node2 a)const {return b<a.b;}
}a[maxn],p[maxn];
int n,m;
vector<int>sb;
map<int,int>mp;
multiset<node2>s;
multiset<node2>::iterator it;
bool cmp1(const node2&a,const node2 &b)
{
if(a.a==b.a)return a.b<b.b;
return a.a<b.a;
}
bool cmp3(const node2&a,const node2&b)
{
return a.id<b.id;
}
void solve()
{
sort(p,p+n,cmp1);
sort(a,a+m,cmp1);
int now=0;
int j=0;
for(int i=0;i<n;i++)
{
while(j<m&&a[j].a<=p[i].a)
{
s.insert(a[j]);j++;
}
it=s.lower_bound(p[i]);
if(it==s.end())
{
printf("NO\n");
return;
}
node2 cmp=*it;
s.erase(it);
p[i].k=cmp.id;
cmp.k--;
if(cmp.k>0)s.insert(cmp);
}
printf("YES\n");
sort(p,p+n,cmp3);
for(int i=0;i<n;i++)printf("%d ",p[i].k+1);
return;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)scanf("%d %d",&p[i].a,&p[i].b),p[i].id=i;
cin>>m;
for(int i=0;i<m;i++)scanf("%d %d %d",&a[i].a,&a[i].b,&a[i].k),a[i].id=i;
solve();
return 0;
}