Bin Packing Problem(线段树 + multiset)

传送门

一道很好的线段树+multiset题目,题目中的给的两个算法分别用线段树和multiset处理。

image
image

#include <bits/stdc++.h>
using namespace std;

const int N = 2e6;
int a[N];
map<int, int> mp;
struct Node{
	int l, r, maxn;
}node[N << 2];
int n, c;
typedef long long ll; 
void pushup(int root){
	node[root].maxn = max(node[root << 1].maxn, node[root << 1 | 1].maxn);
}

void build(int root, int l, int r){	
	node[root].l = l;
	node[root].r = r;
	if(l == r){
		node[root].maxn = c;
		return;
	}	
	int mid = (l + r) >> 1;
	build(root << 1, l, mid);
	build(root << 1 | 1, mid + 1, r);
	pushup(root);
}

void change(int root, int l, int r, int value){
	if(node[root].l == node[root].r){
		node[root].maxn -= value;
		return;
	}
	if(node[root << 1].maxn >= value)
		change(root << 1, l, r, value);
	else
		change(root << 1 | 1, l, r, value);
	pushup(root);
}
int query(int root, int l, int r, int value){
	if(node[root].l == node[root].r){
		return node[root].l;
	}
	if(node[root << 1].maxn >= value)
		return query(root << 1, l, r, value);
	else
		return query(root << 1 | 1, l, r, value);
}
int main(){

	int t;
	scanf("%d", &t);
	while(t --){
		int ans1, ans2;
		multiset<ll> mul;
		scanf("%d%d", &n, &c);
		build(1, 1, n + 20);
		for(int i = 1; i <= n; i ++){
			scanf("%d", &a[i]);	
			if(node[1].maxn >= a[i])
				change(1, 1, n, a[i]);
		}
		if(node[node[1].l].maxn < c)
			printf("%d ", n);
		else{
			int pos = query(1, 1, n, c);
			printf("%d ", pos - node[1].l);	
		}
		ans2 = 1;
		mul.insert(c);
		for(int i = 1; i <= n; i ++){
			if(*mul.rbegin() < a[i]){
				ans2 ++;
				mul.insert(c - a[i]);
			}else{
				multiset<ll>::iterator it = mul.lower_bound(a[i]);
				ll num = *it;
				mul.erase(it);
				mul.insert(num - a[i]);
			}
		}
		printf("%d
", ans2);
		
	}
	
	return 0;
}
原文地址:https://www.cnblogs.com/pureayu/p/14979662.html