1. 程式人生 > 實用技巧 >CF496E Distributing Parts(貪心)題解

CF496E Distributing Parts(貪心)題解

演算法

貪心(黑題?)

思路

考慮如何讓每一位演奏家發揮最大作用,不難發現,當每一位演奏者優先處理自己能力範圍內左端點最小的區間時可以達到最優。

所以,我們可以將樂曲和演奏者按照右端點排序,並用\(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\n"), 0;
	printf("YES\n");
	for(int i = 1; i <= n; ++ i) printf("%d ", Ans[i]);
	printf("\n");
	return 0;
}