LOJ#6039. 「雅礼集训 2017 Day5」珠宝 题解

题目链接

因为物品的价格不超过 \(300\) , 所以考虑每种体积的物品一起处理,然后按照对 % m 的余数分类并 DP.

不难发现由于 DP 转移的权值满足四边形不等式,所以对于 % m 同余的 DP 状态满足决策单调性,因此直接分治解决即可。

\(\Theta (Cn\log 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?' ':'\n');
	return 0;
}
posted @ 2020-09-29 21:09  srf  阅读(308)  评论(0编辑  收藏  举报