[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. D. Eternal Victory(dfs + 思维)

    D. Eternal Victory time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. [BZOJ2730]:[HNOI2012]矿场搭建(塔尖)

    题目传送门 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个 ...

  3. 识别C++编译器编译标准

    cout << __cplusplus<<endl; C++03:__cplusplus = 199711L C++11:__cplusplus = 201103L

  4. 代码审计之seacms v6.54 前台Getshell 复现分析

    1.环境: php5.5.38+apache+seacms v6.54 上一篇文章针对seacms v6.45 进行了分析,官方给出针对修复前台geishell提供的方法为增加: $order = ( ...

  5. word 之 插入删除空行

    好久没有写程序了.有些手生: 在用C#对word进行直接开发操作过程中,为了文档的美观,我们会插入或删除空行. 1.插入空行的代码很简单. Selection 类型的TypeParagraph()函数 ...

  6. 【2】PRD文档介绍

    首先,我想说,题主是一个不严肃的人(严肃脸),所以每次干个啥事之前我都喜欢唠唠嗑,说说废话,沟通沟通感情,曾经以为自己将会成为一个幻想中的产品经理那般大展身手,作为非计算机专业出身的应届生,后来才发现 ...

  7. EBS 创建会计科目 小结

    1 创建会计科目 方式(以AP发票为例) 1)在发票工作台对单张发票进行创建科目: 参考网址: https://www.cnblogs.com/bruce_zhao/p/3809493.html 备注 ...

  8. java中线程状态

    刚开始接触java时,就觉得多线程是一个障碍,不容易理解,当时选择了跳过,不过工作一段时间后,发现这块还是需要深入研究一下的,及时平时工作中不使用多线程,但一定会使用web容器,比如tomcat,也是 ...

  9. php post请求

    public function file_get_contents_post($url, $post){ $options = array( 'http'=> array( 'method'=& ...

  10. 利用uniGUI中的TUniPageControl实现多页面

    远行效果: 实现代码: procedure TfrmMain.OpenForm(Caption,FormClassName:string);var  i:integer;  sheet:TUniTab ...