首页 > 其他分享 >loj6039. 「雅礼集训 2017 Day5」珠宝

loj6039. 「雅礼集训 2017 Day5」珠宝

时间:2023-06-09 22:12:18浏览次数:86  
标签:10 leq ll Day5 bound 雅礼 tail 四边形 loj6039

题目大意

有 \(n\) 个物品,第 \(i\) 个费用为 \(w_i\) ,价值为 \(v_i\) ,对于 \(k\in[1,m]\) 求费用为 \(m\) 时能获得的最大价值。

\(1\leq n\leq 10^6,1\leq m\leq 5\times 10^4,1\leq w_i\leq 300,1\leq v_i\leq 10^9\)


思路

\(n\) 很大,但 \(w_i\) 很小,于是我们考虑以其为突破口。

我们可以把 \(w_i\) 相同的按照 \(v_i\) 从大到小排序,设这里有 \(x_i\) 个相同的 \(w_i\) ,那么对于每个 \(w_i\) ,我们就可以选择 \(0 \sim x_i\) 个。

设 \(f_{i,j}\) 表示 \(w=i\) 时费用为 \(j\) 的最大价值和,那么有

\(f_{i,j}=f_{i-1,j-ki}+s_{i,z}\)

( \(s_{i,z}\) ​表示 \(w=i\) 的物品中前 \(z\) 大的价值和)

这个式子明显是一个01背包的状态转移方程,很难用常规的优化,但是可以用四边形不等式。至于证明,我们有 \(w_{i,j}=s_{j-i}\)

要证明:
\(w_{i,j}+w_{i+1,j+1}\geq w_{i,j+1}+w_{i+1,j}\)
\(s_{j-i}+s_{j-i}\geq s_{j-i+1}+s_{j-i-1}\)
上面两个式子是等价的

因为 \(s_{i+1} - s_{i}\) 是递减的,所以成立。

那么我们现在对于每个枚举的 \(w=i\) ,

先把所有的 $ i*k + j(\ j\in[0,i)\ )$ 都分成一组。

对于每一组我们都可以用四边形不等式优化:

对于所有决策用一个单调队列记录,并且记录 \(z_i\) 表示队列里第 \(i\) 个决策和第 \(i+1\) 个决策的交叉点(在 \(z_i\) 之前 \(q_{i}\) 更优, \(z_i\) 以之后 \(q_{i+1}\) 更优)。

每次弹出队列前面的来找答案,加入的时候我们就二分出队尾和新加入的决策交叉点,然后一直弹尾部直到不交叉。

时间复杂度: \(O(m w \log m)\)

#include<bits/stdc++.h>
#define ll long long
#define N 50010
using namespace std;
ll n,m,g,f[2][N],q[N],z[N];
vector<ll>w[310];
bool cmp(ll x,ll y){
	return x>y;
}
ll calc(ll i,ll j,ll p,ll k){
	return f[!g][i*p+k]+w[p][j-i-1];
}
ll bound(ll i,ll j,ll p,ll k){
	ll l = i+1,r = (m-k)/p;
	while(l<=r){
		ll mid = (l+r)>>1;
		if(calc(i,mid,p,k)<calc(j,mid,p,k))
			l = mid+1;
		else r = mid-1;
	}
	return l;
}
int main(){
	scanf("%lld%lld",&n,&m);
	for(ll i = 1;i<=n;i++){
		ll c,v;
		scanf("%lld%lld",&c,&v);
		w[c].push_back(v);
	}
	g = 0;
	for(ll p = 1;p<=300;p++){
		if(w[p].empty()) continue;
		g^=1;
		memcpy(f[g],f[!g],sizeof(f[g]));
		sort(w[p].begin(),w[p].end(),cmp);
		while(w[p].size()<=m/p) w[p].push_back(0);
		for(ll i = 1;i<w[p].size();i++) w[p][i]+=w[p][i-1];
		for(ll k = 0;k<p;k++){
			ll head = 1,tail = 0;
			for(ll i = 0;i*p+k<=m;i++){
				while(head<tail&&z[head]<=i) head++;
				if(head<=tail) f[g][i*p+k] = max(f[g][i*p+k],calc(q[head],i,p,k));
				while(head<tail&&z[tail-1]>=bound(i,q[tail],p,k)) tail--;
				z[tail] = bound(i,q[tail],p,k);
				q[++tail] = i;
			}
		}
	}
	for(ll i = 1;i<=m;i++)
		printf("%lld ",f[g][i]);
	return 0;
}

为此我还专门学了四边形不等式优化

标签:10,leq,ll,Day5,bound,雅礼,tail,四边形,loj6039
From: https://www.cnblogs.com/cztq/p/17470352.html

相关文章

  • 每日一练 | 华为认证真题练习Day56
    1、iproute-static10.0.12.0255.255.255.0192.168.1.1关于此命令描述正确的是()。A.如果路由器通过其他协议学习到和此路由相同目的网络的路由,路由器将会优先选择此路由B.此命令配置了一条到达10.0.12.0网络的路由C.该路由的优先级为100D.此命令配置了一条到达192.168.1.1网......
  • 算法学习day50动态规划part11-123、188
    packageLeetCode.DPpart11;/***123.买卖股票的最佳时机III*给定一个数组,它的第i个元素是一支给定的股票在第i天的价格.*设计一个算法来计算你所能获取的最大利润。你最多可以完成两笔交易。*注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。......
  • 算法学习day51动态规划part12-309、714
    packageLeetCode.DPpart12;/***309.最佳买卖股票时机含冷冻期*给定一个整数数组prices,其中第prices[i]表示第i天的股票价格。*设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):*卖出股票后,你无法在第二天买入......
  • 软件测试day5
    等价类划分  (重点:SRS----需求规格说明书)常见考题(记):边界值 ......
  • MySQL学习进阶篇Day5
    2.6.4索引失效情况2.6.4.1索引列运算不要在索引列上进行运算操作,索引将失效。 在tb_user表中,除了前面介绍的联合索引之外,还有一个索引,是phone字段的单列索引。 A.当根据phone字段进行等值匹配查询时,索引生效。explainselect*fromtb_userwherephone='1779......
  • 小灰灰深度学习day5——数据预处理
    内容简介:1.将数据写入.csv文件中    2.将数据从.csv文件中读出  3.利用插值法处理缺失的数据  4.将数据类型转化为torch张量类型代码如下:importosos.makedirs(os.path.join('..','data'),exist_ok=True)data_file=os.path.join('..','data','house_......
  • 瑞吉外卖day5
    套餐管理业务新增套餐需求分析套餐救赎菜品的集合,后台管理系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐数据模型所以在新增套餐时,涉......
  • MySQL学习基础篇Day5
    4.约束4.1概述概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。目的:保证数据库中数据的正确、有效性和完整性。分类:约束描述关键字非空约束限制该字段的数据不能为nullNOTNULL唯一约束保证该字段的所有数据都是唯一、不重复的......
  • DAY5
    DAY5静态路由准备路由:给数据包指路静态路由:人工配置动态路由:提前配置一些指令,路由器自己学习网关是优先级最低的静态路由直连路由静态路由:路由器转发功能1.echo‘ner.ipv4.ip_forward=1'>>/etc/sysctl.conf2.sysctl-psystemctlrestartnetwork重启计......
  • 闲话 Day5
    事实证明,更新间隔是以指数速度增长的。虽然但是,不是说PKU比THU好过吗。。。两个决定了去PKU的结果PKU没过,啊对对对。想要写一个色は匂へど散りぬるを。但是好像很难打出来的样子啊,那没事了。原曲神々が恋した幻想郷,也推荐听一听。这个可以方便的搜出来。行了直接......