2020ZJCPC------B. Bin Packing Problem

题意:

n个物品,第i个物品的容量是 a[i] ,有无限个箱子,每个箱子的容量是 c ,问按照一下两种放法,最少需要几个箱子。
第一种:每次都选择最前面的可以放在物品的箱子,若不存在就增加一个箱子。
第二种:每次都选择剩余容量最小的且可以容纳物品的箱子,若不存在就增加一个箱子。

思路:

第一种:用线段树维护区间最大值,然后直接在线段树上用 log(n) 的复杂度去查询即可。
第二种:用multiset去维护每个箱子的剩余容量,用lower_bound查询。
时间复杂度:n*logn 。

代码:

//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long
#define MOD 998244353
#define pdd pair<double,double>
#define mem(a,x) memset(a,x,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
const long long INF = 1e18+5;
const int inf = 0x3f3f3f3f;  
const double eps=1e-6;       
const int maxn=3000;       
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(int &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}

ll n,m,c;
struct node
{
    ll l,r,data;
    ll lt;    
}tree[1000010*4];
ll a[1000010];
void build(ll l,ll r,ll index)
{
    tree[index].lt=0;
    tree[index].l=l;
    tree[index].r=r;
    tree[index].data=c;
    if(tree[index].l==tree[index].r)
    {
        return ;
    }
    ll mid=(l+r)/2;
    build(l,mid,index*2);
    build(mid+1,r,index*2+1);
    tree[index].data=max(tree[index*2].data,tree[index*2+1].data);
}
void push_down(ll index)
{
    if(tree[index].lt!=0)
    {
        tree[index*2].lt=tree[index].lt;
        tree[index*2+1].lt=tree[index].lt;
        tree[index*2].data+=tree[index].lt;
        tree[index*2+1].data+=tree[index].lt;
        tree[index].lt=0;
    }
}
void up_data(ll index,ll u,ll k)          //更新
{
    if(tree[u].l==tree[u].r)
    {
        tree[u].data+=k;
        tree[u].lt+=k;
        return ;
    }
    push_down(u);
    ll mid=(tree[u].l+tree[u].r)>>1;
    if(mid>=index)
        up_data(index,u*2,k);
    else
        up_data(index,u*2+1,k);
    tree[u].data=max(tree[u*2].data,tree[u*2+1].data);
}
ll search(ll u,ll val)
{
    if(tree[u].l==tree[u].r)
        return tree[u].l;
    push_down(u);
    if(tree[u*2].data>=val)
        return search(u*2,val);
    else
        return search(u*2+1,val);
}
multiset<ll>st;
int main()
{
    int T;
    cin>>T;
    while(T--){
        st.clear();
        scanf("%lld%lld",&n,&c);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        build(1,n,1);
        ll max_root=0;
        for(int i=1;i<=n;i++){
            ll pos=search(1,a[i]);
            //cout<<pos<<endl;
            if(pos>max_root){
                max_root=pos;
            }
            up_data(pos,1,-a[i]);
        }
        ll max_root2=1;
        st.insert(c);
        for(int i=1;i<=n;i++){
            if(*st.rbegin()<a[i]){
                max_root2++;
                st.insert(c-a[i]);
            }else{
                multiset<ll>::iterator it;
                it=st.lower_bound(a[i]);
                ll num=*it;
                st.erase(it);
                st.insert(num-a[i]);
            }
        } 
        printf("%lld %lld\n",max_root,max_root2);
    }
    return 0;
}

posted @ 2020-10-26 18:13  hachuochuo  阅读(526)  评论(0编辑  收藏  举报