感觉这个题已经变成经典题了…
考虑CDQ分治,solve(l,r)表示删掉[l,r]这段区间的物品后的背包数组,那么solve(l,mid)这个背包数组一定包含(mid+1,r)里的所有物品,所以只需用(mid+1,r)这些物品更新solve(l,r)这个背包后传入solve(l,mid)即可。 solve(mid+1,r)时同理,用(l,mid)的物品更新solve(l,r)这个背包,然后传入solve(mid+1,r)即可。
在递归边界solve(l,l)的时候更新答案。
复杂度:T(n)=2T(n/2)+O(nM)≈O(nlognM)
为了保证复杂度,需要单调队列优化下多重背包…
(顺便吐槽下网上的题解怎么都是正着做一遍背包反着做一遍背包然后合并,这复杂度3E啊…数据水就过了…)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
//by:MirrorGray
using namespace std;
const int N=611111,V=2111;
int dp[15][V],ans[N];
int c[N],limit[N],w[N];
int tot=-1,head[N],nxt[N],pos[N],money[N];
struct queue{
int pos,val;
queue(int a=0