Bin Packing Problem

题意

让你解决一个装箱问题,给你两种算法,让你求用这两种算法解决问题得到的方案

解题思路

对于第一种方法,用线段树维护区间最大值,要注意需要先判断左边以保证找到最前面的。
对于d第二种方法,使用lower_bound直接模拟即可

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

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);
}


int main() {
    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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值