因为物品的价格不超过 (300) , 所以考虑每种体积的物品一起处理,然后按照对 % m 的余数分类并 DP.
不难发现由于 DP 转移的权值满足四边形不等式,所以对于 % m 同余的 DP 状态满足决策单调性,因此直接分治解决即可。
(Theta (Cnlog n))
code :
#include <bits/stdc++.h>
#define LL long long
using namespace std;
template <typename T> void read(T &x){
static char ch; x = 0,ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
inline void write(LL x){if (x > 9) write(x/10); putchar(x%10+'0'); }
const int N = 50005;
vector<int>G[305];
LL f[N],g[N],val[N];
int n,id[N],len;
inline void divide(int l,int r,int pl,int pr){
int i,mid = l+r>>1,p = pl;
for (i = pl; i <= pr && i <= mid; ++i) if (g[id[i]] + val[mid-i] > f[id[mid]])
f[id[mid]] = g[id[i]] + val[mid-i],p = i;
if (l < mid) divide(l,mid-1,pl,p); if (mid < r) divide(mid+1,r,p,pr);
}
inline void DP(int st,int l){
id[len=1] = st,st += l; while (st <= n) id[++len] = st,st += l;
divide(1,len,1,len);
}
inline void work(int s){
int i,ll = n/s;
for (val[0] = 0,i = 1; i <= G[s].size() && i <= ll; ++i) val[i] = val[i-1] + G[s][i-1];
for (i = G[s].size() + 1; i <= ll; ++i) val[i] = val[i-1];
memcpy(g,f,n+1<<3),memset(f,0,sizeof(f));
for (i = 0; i < s && i <= n; ++i) DP(i,s);
// for (i = 1; i <= n;)
}
inline void get_goods(){
int m,x,y; read(m),read(n);
while (m--) read(x),read(y),G[x].push_back(y);
for (int i = 1; i <= 300; ++i) if (G[i].size()) sort(G[i].begin(),G[i].end()),reverse(G[i].begin(),G[i].end());
}
int main(){
int i;
get_goods();
for (i = 1; i <= 300; ++i) if (G[i].size()) work(i);
for (i = 1; i <= n; ++i) write(f[i]),putchar(i<n?' ':'
');
return 0;
}