题意:按顺序(记住放入物品的顺序是给定的)给一串序列,代表物品的重量,并且给定容器的容量大小, 要求最少需要几个容器存放这些物品。
题中给了两种算法:
- 从前往后遍历容器,找到第一个可以放的容器,把物品放进去,如果放不了,再开一个位置
- 找到能放并且当前剩余容量最小的容器,如果放不下,再开一个位置
第一个算法按照朴素算法,需要n2的复杂度。但我们可以考虑维护区间的最值,如果可以往左找就一直往左,直到找到。因此可以考虑线段树,我们维护区间的最值,初始值全部赋值为容量,如果当前放的物品体积小于左子树的最大值,那么可以往左子树递归,否则向右递归。
第二个算法是最优原则,题解所给的做法是利用set,但我一直被卡,所以尝试用map基于红黑树的原理来查找,记住查找时用map自带的lower_bound,效率可以提升很多。
附上ac代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <cmath>
#include <bitset>
#include <map>
using namespace std;
//#define ACM_LOCAL
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
const int N = 1e6 + 5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int a[N];
int n, c, T;
struct node {
int l, r;
int maxx;
int tag;
}t[N<<2];
void push_up(int u) {
t[u].maxx = max(t[u<<1].maxx, t[u<<1|1].maxx);
}
void push_down(int u) {
if (t[u].tag != 0) {
t[u<<1].tag = t[u].tag;
t[u<<1|1].tag = t[u].tag;
t[u<<1].maxx += t[u].tag;
t[u<<1|1].maxx += t[u].tag;
t[u].tag = 0;
}
}
void build(int l, int r, int u) {
t[u].l = l, t[u].r = r;
t[u].maxx = c;
t[u].tag = 0;
if (t[u].l == t[u].r) {
return;
}
int mid = (l + r) >> 1;
build(l, mid, u<<1);
build(mid+1, r, u<<1|1);
push_up(u);
}
void update(int pos, int u, int v) {
if (t[u].l == t[u].r) {
t[u].maxx += v;
t[u].tag += v;
return;
}
push_down(u);
int mid = (t[u].l + t[u].r) >> 1;
if (pos <= mid) update(pos, u<<1, v);
else update(pos, u<<1|1, v);
push_up(u);
}
int query(int val, int u) {
if (t[u].l == t[u].r) {
return t[u].l;
}
push_down(u);
if (val <= t[u<<1].maxx) return query(val, u<<1);
else return query(val, u<<1|1);
}
void solve () {
scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &c);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, n, 1);
int Max_bot = 0;
for (int i = 1; i <= n; i++) {
int pos = query(a[i], 1);
Max_bot = max(Max_bot, pos);
update(pos, 1, -a[i]);
}
map<int, int> mp;
mp[c] = 1;
for (int i = 1; i <= n; i++) {
auto it = mp.lower_bound(a[i]);
if (it == mp.end()) {
mp[c-a[i]]++;
}
else {
mp[it->first - a[i]] ++;
mp[it->first]--;
if (mp[it->first] == 0) mp.erase(it);
}
}
int Max_bot_2 = 0;
for (auto x : mp) Max_bot_2 += x.second;
printf("%d %d\n", Max_bot, Max_bot_2);
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}