题意:
就是有n个物品,然后有体积为m的盒子,然后有两种算法。第一种,顺序遍历每个物品,找到第一个能装下它的盒子,如果没有,那么就新添一个盒子。第二种,顺序遍历每个物品,找到能装下它的提及剩余最小的盒子,如果没有,那么就新添一个盒子。问你两种算法分别要多少种盒子。
思考:
对于第二种很简单,就是multiset跑一遍就行了。对于第一种,刚开始我还想vector,但是vector要满足是升序的呀。所以就想到了线段树,如果最大值都装不下,那么新开一个盒子。如果能装下,那么就去装,对于怎么找到第一个大于它的点,刚开始我想了个二分找最近点,但是nloglog应该是超时的。一想既然就是单点修改,直接写个change函数,尽量往左走,最后修改就行了呀。还有一点就是,对于change和update函数,之类的,后面都要加上pushup,如果有pushdown,那么每个函数都要有pushup。
代码:
#include<bits/stdc++.h>
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define node_l node<<1
#define node_r node<<1|1
using namespace std;
const int inf = 1e18;
const int N = 1e6+10,M = 2000;
struct Node{
int L,R;
int sum;
int maxn;
}t[4*N];
int T,n,m;
int va[N];
void build(int node,int l,int r)
{
t[node].sum = t[node].maxn = 0;
t[node].L = l,t[node].R = r;
if(l==r)
{
return ;
}
int mid = (l+r)>>1;
build(node_l,l,mid);build(node_r,mid+1,r);
}
void update(int node,int x,int value)
{
if(t[node].L==x&&t[node].R==x)
{
t[node].sum = value;
t[node].maxn = value;
return ;
}
int mid = (t[node].L+t[node].R)>>1;
if(x<=mid) update(node_l,x,value);
else update(node_r,x,value);
t[node].maxn = max(t[node_l].maxn,t[node_r].maxn);
}
int query(int node,int l,int r)
{
if(t[node].L>=l&&t[node].R<=r) return t[node].maxn;
int mid = (t[node].L+t[node].R)>>1;
if(r<=mid) return query(node_l,l,r);
else if(l>mid) return query(node_r,l,r);
else return max(query(node_l,l,mid),query(node_r,mid+1,r));
}
void change(int node,int ned)
{
if(t[node].L==t[node].R)
{
t[node].sum -= ned;
t[node].maxn -= ned;
return ;
}
if(t[node_l].maxn>=ned) change(node_l,ned);
else change(node_r,ned);
t[node].maxn = max(t[node_l].maxn,t[node_r].maxn);
}
int solve1()
{
int idx = 0;
build(1,1,n);
for(int i=1;i<=n;i++)
{
if(!idx||query(1,1,idx)<va[i])
{
update(1,++idx,m-va[i]);
continue;
}
change(1,va[i]);
}
return idx;
}
int solve2()
{
int ans = 0;
multiset<int > s;
for(int i=1;i<=n;i++)
{
auto idx = s.lower_bound(va[i]);
if(idx==s.end())
{
ans++;
s.insert(m-va[i]);
}
else
{
int now = *idx;
s.erase(s.find(now));
s.insert(now-va[i]);
}
}
return ans;
}
signed main()
{
IOS;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>va[i];
cout<<solve1()<<" "<<solve2()<<"\n";
}
return 0;
}
总结:
多多思考呀。