Loj#6039-「雅礼集训 2017 Day5」珠宝【四边形不等式,dp】

1|0正题

题目链接:https://loj.ac/p/6039


1|1题目大意

n个物品,第i个费用为wi,价值为vi,对于k[1,m]求费用为m时能获得的最大价值。

1n106,1m5×104,1wi300,1vi109


1|2解题思路

好早以前写的不过不知道为啥错了,现在来补个新的。

wi很小,考虑以其为突破口,显然地我们可以把wi相同的按照vi从大到小排序,那么对于每个wi,我们就可以选择若干个。

fi,j表示做到w=i时费用为j的最大价值和,那么有

fi,j=fi1,jki+si,z

si,z表示w=i的物品中前z大的价值和)

这个式子很难用常规的优化,但是可以用四边形不等式。至于证明,我们有wi,j=sji
要证明

wi,j+wi+1,j+1wi,j+1+wi+1,j

sji+sjisji+1+sji1

然后因为si+1si是递减的,所以成立。

那么我们现在对于每个枚举的w=i,把所有的ik+j( j[0,i) )都分成一组。

然后对于每一组我们都用四边形不等式优化,不过我忘了优化的方法了,还是记一下吧:

对于所有的可能的决策我们用一个单调队列记录,顺带记录zi表示队列里第i个决策和第i+1个决策的交叉点(在zi之前qi更优,zi以之后qi+1更优)。

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

时间复杂度:O(mwlogm)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long using namespace std; const ll N=5e4+10; 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; } signed main() { freopen("jewelry.in","r",stdin); freopen("jewelry.out","w",stdout); scanf("%lld%lld",&n,&m); for(ll i=1,c,v;i<=n;i++){ 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])); // memset(f[g],0,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; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15719451.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(110)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示