[NAIPC2016]Jewel Thief(决策单调性+分治)

题面

原题提交地址(题目编号H)

原题面下载地址

有\(n\)个物品,每个物品有一个体积\(w_i\)和价值\(v_i\),现在要求对\(V \in [1,m]\),求出体积为\(V\)的

背包能够装下的最大价值

\(1 ≤ n ≤ 1000000; 1 ≤ m ≤ 100000; 1 ≤ w_i ≤ 300; 1 ≤ v_i ≤ 10^9\)

分析

决策单调性发现

注意到物品的体积很小,考虑按体积分类,选取同种体积的物品时,一定优先选择价值大的物品。

设\(dp[i][j]\)为使用前i种体积的物品,体积为j的最大价值。类似多重背包的单调队列优化,将模i同余的所有位置拿出来重新标号(即下标看作1,2,3....x)。

则有

\[dp[i][j]=\max_{k=0}^j dp[i-1][k]+val(k,j)
\]

其中\(w(k,j)\)表示第\(i\)种体积的物品中,最大的\(j-k\)个的价值和

显然\(val\)满足四边形不等式。

问题转化

令\(A\)为一个矩阵,\(pos(j)=max(\{i|,\forall p \in [0,m],A[i][j]>A[p][j] \})\),即使得第\(j\)列第\(i\)行的值最大的\(i\)(如果有多个i相同,则取编号最大的)

在原问题中,考虑第\(i-1\)层到第\(i\)层的转移 ,令\(A[k][j]=\begin{cases} dp[i-1][k]+val(k,j),k \leq j \\ -\infty,k>j\end{cases}\),我们发现dp的转移实际上就是在求第\(k\)行第\(j\)列的最大值,其中\(j\)固定。那么\(dp[i][j]=A[pos(j)][j]\)

于是问题就转化为:已知一个\((m+1)\times(m+1)\)大小的矩阵\(A\),其中每个元素的值均可以在\(O(1)\)时间内查询。现

要求对于\(j \in [0,m]\),求出\(A[pos(j)][j]\)

分治求解

对列[l,r]进行分治,维护当前可能成为\(pos\)的行\([x,y]\),令\(mid=\frac{l+r}{2}\),暴力枚举所有可能的行求出\(pos(mid)\),分治递归操作\([l,mid-1] [x,pos(mid)]\)以及\([mid +1,r] [pos(mid),y]\)直至\(l = r\)或\(x = y\)。容易发现这样的时间复杂度是\(O(m\log m)\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define maxw 300
#define maxn 1000000
using namespace std;
typedef long long ll;
vector<ll>w[maxw+5];
ll dp[2][maxn+5];
int n,m;
void divide(int l,int r,int x,int y,int now,int mod,int rest){
//列[l,r],行[x,y];
if(l>r) return;
int mid=(l+r)>>1,pos=mid;
dp[now^1][mid*mod+rest]=dp[now][mid*mod+rest];
for(int j=min(y,mid-1);j>=x;j--){//枚举可能成为pos(mid)的列,注意j<mid
if(mid-j>(int)w[mod].size()) break;
if(dp[now][j*mod+rest]+w[mod][mid-j-1]>dp[now^1][mid*mod+rest]){
dp[now^1][mid*mod+rest]=dp[now][j*mod+rest]+w[mod][mid-j-1];
pos=j;
}
}
divide(l,mid-1,x,pos,now,mod,rest);
divide(mid+1,r,pos,y,now,mod,rest);
} inline int cmp(int x,int y){
return x>y;
}
int main(){
int x,y;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d %d",&x,&y);
w[x].push_back(y);
}
for(int i=1;i<=maxw;i++){
sort(w[i].begin(),w[i].end(),cmp);
for(int j=1;j<(int)w[i].size();j++) w[i][j]+=w[i][j-1];
}
int now=0;
for(int i=1;i<=300;i++){
if(w[i].size()){
for(int j=0;j<i;j++){
//将模i同余的所有位置拿出来
divide(0,(m-j)/i,0,(m-j)/i,now,i,j);
}
for(int j=1;j<=m;j++){
dp[now^1][j]=max(dp[now^1][j],dp[now^1][j-1]);
//我们dp的子状态是体积<=j,而分治过程中是=j
}
now^=1;
}
}
for(int i=1;i<=m;i++) printf("%I64d ",dp[now][i]);
}

[NAIPC2016]Jewel Thief(决策单调性+分治)的更多相关文章

  1. P2877 [USACO07JAN]牛校Cow School(01分数规划+决策单调性分治)

    P2877 [USACO07JAN]牛校Cow School 01分数规划是啥(转) 决策单调性分治,可以解决(不限于)一些你知道要用斜率优化却不会写的问题 怎么证明?可以暴力打表 我们用$ask(l ...

  2. 4951: [Wf2017]Money for Nothing 决策单调性 分治

    Bzoj4951:决策单调性 分治 国际惯例题面:一句话题面:供应商出货日期为Ei,售价为Pi:用户收购截止日期为Si,收购价格为Gi.我们要求max((Si-Ej)*(Gi-Pj)).显然如果我们把 ...

  3. P3515 [POI2011]Lightning Conductor(决策单调性分治)

    P3515 [POI2011]Lightning Conductor 式子可转化为:$p>=a_j-a_i+sqrt(i-j) (j<i)$ $j>i$的情况,把上式翻转即可得到 下 ...

  4. bzoj1897. tank 坦克游戏(决策单调性分治)

    题目描述 有这样一款新的坦克游戏.在游戏中,你将操纵一辆坦克,在一个N×M的区域中完成一项任务.在此的区域中,将会有许多可攻击的目标,而你每摧毁这样的一个目标,就将获得与目标价值相等的分数.只有获得了 ...

  5. [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)

    显然有决策单调性,但由于逆序对不容易计算,考虑分治DP. solve(k,x,y,l,r)表示当前需要选k段,待更新的位置为[l,r],这些位置的可能决策点区间为[x,y].暴力计算出(l+r)/2的 ...

  6. [loj6039]「雅礼集训 2017 Day5」珠宝 dp+决策单调性+分治

    https://loj.ac/problem/6039 我们设dp[i][j]表示考虑所有价值小于等于i的物品,带了j块钱的最大吸引力. 对于ci相同的物品,我们一定是从大到小选k个物品,又发现最大的 ...

  7. bzoj4518: [Sdoi2016]征途(DP+决策单调性分治优化)

    题目要求... 化简得... 显然m和sum^2是已知的,那么只要让sigma(si^2)最小,那就变成了求最小平方和的最小值,经典的决策单调性,用分治优化即可. 斜率优化忘得差不多就不写了 #inc ...

  8. 2019.02.21 bzoj2739: 最远点(决策单调性+分治)

    传送门 题意简述:给一个N个点的凸多边形,求离每一个点最远的点. 思路:先根据初中数学知识证明决策是满足单调性的,然后上分治优化即可. 才不是因为博主懒得写二分+栈优化呢 代码: #include&l ...

  9. [BZOJ4367][IOI2014]Holiday(决策单调性+分治+主席树)

    4367: [IOI2014]holiday假期 Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 421  Solved: 128[Submit][Sta ...

随机推荐

  1. Codeforces 514 D R2D2 and Droid Army(Trie树)

    题目链接 大意是判断所给字符串组中是否存在与查询串仅一字符之差的字符串. 关于字符串查询的题,可以用字典树(Trie树)来解,第一次接触,做个小记.在查询时按题目要求进行查询. 代码: #define ...

  2. Linux之zookeeper开机启动

    1.用cd 命令切换到/etc/rc.d/init.d/目录下 [root@bogon ~]# cd /etc/rc.d/init.d 2.用touch zookeeper创建一个文件 [root@b ...

  3. PHP-windows下安装

    下载 Apache下载地址:http://httpd.apache.org/download.cgi PHP下载地址:http://php.net/downloads.php 解压 解压到安装路径下H ...

  4. Git常用命令详解

    1.创建版本库 git clone <url> #克隆远程版本库 git init #初始化本地版本库 通过 ls -ah 可以看到隐藏的.git目录 2.修改和提交 添加文件readme ...

  5. IDEA下载安装及绿色方法

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  6. LeetCode 145. 二叉树的后序遍历(Binary Tree Postorder Traversal)

    题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 后 ...

  7. Java Jsch SFTP 递归下载文件夹

    Java Program For Downloading Folder Content recursively from SFTP Server How to download folder from ...

  8. Python将函数放入模块

    函数可以将通用的代码封装起来,便于其他程序或者方法调用.将函数存放在文件中,这个文件被称为模块.将函数存储在独立的模块中,可与其他程序员共享这些文件而不是整个程序. fun.py def say_hi ...

  9. go get命令在go mod目录下与正常目录执行的区别

    转载自https://www.jianshu.com/p/0a2ebb07da54 非$GOPATH目录下的go mod项目 $ go mod init test $ cat go.mod modul ...

  10. shell做成csv文件

    echo a,b,c,d >aa.csv 其实就是用逗号做分隔符