算法
贪心(黑题?)
思路
考虑如何让每一位演奏家发挥最大作用,不难发现,当每一位演奏者优先处理自己能力范围内左端点最小的区间时可以达到最优。
所以,我们可以将乐曲和演奏者按照右端点排序,并用(set)维护乐曲左端点,对于每一个演奏者,将ta的左端点({lower\_bound})一下就好了。
注意
如果你用的是结构体,那建议使用(multiset),因为可能出现重复元素。
参考代码
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
const int maxn = 1e5 + 10;
int n,m,Ans[maxn];
struct R{
int l,r,k,id;
}a[maxn],b[maxn];
struct node{
int val,id;
friend bool operator<(node x, node y){
return x.val < y.val;
}
}tmp;
multiset<node> s;
bool cmp(R x, R y){return x.r < y.r;}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) scanf("%d%d", &a[i].l, &a[i].r), a[i].id = i;
scanf("%d", &m);
for(int i = 1; i <= m; ++ i) scanf("%d%d%d", &b[i].l, &b[i].r, &b[i].k), b[i].id = i;
sort(a + 1, a + 1 + n, cmp); sort(b + 1, b + 1 + m, cmp);
int j = 1;
for(int i = 1; i <= m; ++ i){
while(a[j].r <= b[i].r && j <= n){
tmp.id = a[j].id;
tmp.val = a[j].l;
s.insert(tmp); j++;
}
while(b[i].k){
auto it = s.lower_bound((node){b[i].l, 0});
if(it == s.end()) break;
Ans[it->id] = b[i].id; b[i].k--; s.erase(it);
}
}
for(int i = 1; i <= n; ++ i) if(!Ans[i]) return printf("NO
"), 0;
printf("YES
");
for(int i = 1; i <= n; ++ i) printf("%d ", Ans[i]);
printf("
");
return 0;
}