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;
}
越自律,越自由