• LOJ 6039 珠宝


    LOJ #6039 珠宝

    题意:

    01背包

    数据范围:

    (1 leq N leq 1000000, 1 leq K leq 50000, 1 leq C_i leq 300, 0 leq V_i leq 10 ^ 9)

    题解:

    考虑每个物品的代价不同的只有不多于 (300) 个,把相同代价的物品分成一类同时进行 (dp)

    先考虑相同代价的物品价值都相同,这就是一个单调队列优化多重背包,把这种思想类比到价值不同的情况下。

    根据贪心,相同代价时肯定优先选择价值高的物品,设 (w_{i,j}) 为取 (j) 个代价为 (i) 的最大价值,显然 (w_{i,j}) 为把所有代价为 (i) 的物品价值按从大到小排序后的前缀和。

    (dp_{i,j}) 为只选了代价小于等于 (i) 的物品且总代价小于等于 (j) 的最大价值,显然我们有转移方程为 (dp_{i,j}=max(dp_{i-1,j-ki}+w_{i,j}))

    但是可以发现 (w_i) 是一个凸函数,并不能直接用单调队列转移(可能后来居上,但单调队列并没有反应)。可以再维护一个 (T)(T_i)(i) 最早被单调队列中下一个决策更劣的时间,可以二分找。

    每次找决策点时,看一看队首是否已经不是最优。插入一个决策点时,如果当前队尾比队尾前一个更优的时间大于等于队尾比新决策点更劣的时间,则这个队尾决策一定不会被用到,直接弹出。

    复杂度为 (mathcal{O}(max(C_i)Klog N))

    代码实现:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int q[100005],h,t;
    int f[50005],g[50005],T[50005],n,m;
    vector<int>w[305];
    int gettime(int l,int r,int x,int s) {
    	int L=r+1,R=l+w[x].size(),ans=l+w[x].size()+1;
    	while(L<=R) {
    		int mid=(L+R)>>1;
    		if(f[r*x+s]+w[x][mid-r-1]<f[l*x+s]+w[x][mid-l-1]) L=mid+1;
    		else ans=mid,R=mid-1;
    	} return ans;
    }
    void DP(int x) {
    #define I (i*x+s)
    	memset(T,0x3f,sizeof(T));
    	memset(g,0,sizeof(g));
    	for(int s=0;s<x;s++) {
    		q[h=t=1]=0; g[s]=f[s];
    		for(int i=1;I<=m;i++) {
    			while(h<=t&&T[q[h]*x+s]<=i) h++; g[I]=max(f[q[h]*x+s]+w[x][i-q[h]-1],f[I]);
    			while(h<t&&T[q[t-1]*x+s]>=gettime(q[t],i,x,s)) t--;
    			T[q[t]*x+s]=gettime(q[t],i,x,s); q[++t]=i; T[I]=0x3f3f3f3f;
    		}
    	} for(int i=1;i<=m;i++) f[i]=max(g[i],f[i]);
    #undef I
    }
    signed main() {
    	scanf("%lld%lld",&n,&m);
    	for(int i=1,s,v;i<=n;i++) scanf("%lld%lld",&s,&v),w[s].push_back(v);
    	for(int i=1;i<=300;i++) {
    		if(!w[i].size()) continue ;
    		sort(w[i].begin(),w[i].end());
    		reverse(w[i].begin(),w[i].end());
    		for(int j=1;j<w[i].size();j++) w[i][j]+=w[i][j-1];
    		DP(i);
    	} for(int i=1;i<=m;i++) printf("%lld ",f[i]);
    }
    
  • 相关阅读:
    Kubernetes-一文详解ServiceAccount与RBAC权限控制
    删除无用的docker镜像与容器
    How do I write one to many query in Dapper.Net?
    c# 使用反射Reflection的Emit实现动态创建元数据及可执行文件
    IE浏览器下bootStrap form-control input输入框不显示兼容性问题
    WPF控件从一个窗口移动到另一个窗口,特别适合实时刷新的
    添加/扫描显示二维码中的换行之【另类视野】
    各浏览器官方离线版下载地址
    CentOS挂载NTFS
    System.Data.SQLite.Core for .NET 5 Core manual reference
  • 原文地址:https://www.cnblogs.com/ynyyyds/p/14209247.html
Copyright © 2020-2023  润新知