雅礼集训2017 珠宝

这题看题面发现这是一个标准的背包,尝试寻找突破口,突然发现ci300,所以考虑把ci相同的珠宝放在一起转移

对于同一个代价的物品肯定是优先选择价值较大的,于是我们把同代价的物品按照价值从大到小排序,并且累计前缀和,这些每次会选一些点,很容易可以想到这个选点具有决策单调性

然后是用分治(即应用决策单调性)优化dp

点击查看代码
//CAN'T FORGET
//CAN'T FORGET
//CAN'T FORGET

//#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define _ 0
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
vector<long long> g[305];
long long dp[305][maxn];
int a[maxn],nm;
void solve(int l,int r,int L,int R,int x)
{
	if(l>r)
		return ;
	int mid=(l+r)>>1,pos=L;
	for(int i=max(L,mid-(int)g[x].size());i<=min(mid,R);i++)
	{
		long long w;
		if(i==mid)
			w=0;
		else
			w=g[x][mid-i-1];
		if(dp[x][a[mid]]<dp[x-1][a[i]]+w)
		{
			dp[x][a[mid]]=dp[x-1][a[i]]+w;
			pos=i;
		}
	}
	solve(l,mid-1,L,pos,x);
	solve(mid+1,r,pos,R,x);
}
bool cmp(int x,int y)
{
	return x>y;
}
int main(){
	freopen("jewelry.in","r",stdin);
	freopen("jewelry.out","w",stdout);
	int n=read(),m=read();
    int maxv=0;
    for(int i=1;i<=n;i++)
    {
    	int c=read(),v=read();
    	maxv=max(maxv,c);
    	g[c].push_back(v);
	}
	for(int i=1;i<=maxv;i++)
    {
    	sort(g[i].begin(),g[i].end(),cmp);
    	for(int j=1;j<g[i].size();j++)
    		g[i][j]+=g[i][j-1];
	}
	for(int i=1;i<=maxv;i++)
	{
		for(int j=0;j<=i-1;j++)
		{
			nm=0;
			for(int k=j;k<=m;k+=i)
				a[++nm]=k;
			solve(1,nm,1,nm,i);
		}
	}
	for(int i=1;i<=m;i++)
		cout<<dp[maxv][i]<<" ";
	cout<<endl;
	return ~~(0^_^0);
}
/*
Notes:
1.看所有题目
2.注意数据范围
3.想想自己还能做什么而不是做了什么
4.看清题目!!!
5.记得把调试代码删掉!!!!
6.longlong时 1要写成1ll
7.Think twice code once, think once code forever!
*/
posted @   zxi8_May  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示