LINK


懒得搬题面

简要题意:n个物品,每个物品有一个价格和一个吸引力,问你对于\(i \in [1,k]\),花费i的价格能得到的最大吸引力

其中价格的范围很小,在\([1,300]\)范围内

思路

首先想到一个dp

\(dp_{i,j}\)表示用对于价格小于等于i的物品花费j的价格能得到的最大吸引力

然后对于相等的价格的物品,有一个贪心的的思想就是个数确定的时候选取最大吸引力的几个

这个可以前缀和预处理出来

然后考虑对于价格相等的时候

如果对于\(dp_{w,p}的决策点i < j\),存在\(dp_{w-1,i} + sum[i->p] < dp_{w-1,j} + sum[j->p]\)

那么因为很显然sum这个函数是斜率单调递减的所以可以得到对于任何\(dp_{w,-}\),i一定不会比j更优

所以这样对于w相同的情况就可以处理了

然是题目中的w不完全相同怎么办?

那就强行把w变成相同的就可以了对于\(dp_{w,-}\)我们只考虑不够w的补上多余的价格变成w就可以了

然是这样有可能算不完全,所以对于每一个小于c的数都需要当成决策点来计算一遍

然后一个决策点只会从和它对于c同余相等的决策点转移

这样一定是最优的

然后直接for计算所有可能的决策点

但是为什么需要分治算法呢?

因为虽然有决策点单调的性质,但是我们并不能快速计算出决策点

所以可以考虑分治,枚举中间的决策点然后递归成两个区间分别求解,这样的复杂度是有保障的


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define for_up(a, b, c) for (int a = b; a <= c; ++a)
#define for_down(a, b, c) for (int a = b; a >= c; --a)
#define for_vector(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x){
bool w = 1;x = 0;
char c = getchar();
while(!isdigit(c) && c != '-')c = getchar();
if(c == '-')w = 0, c = getchar();
while(isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if(!w)x=-x;
}
template <typename T>
void Write(T x){
if(x < 0) {
putchar('-');
x=-x;
}
if(x > 9)Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e6 + 10;
const int M = 5e4 + 10;
const int C = 3e2 + 10;
int n, k, maxc = 0;
int c[N], v[N];
int ind, table[N];
ll dp[C][M];
vector<ll> bag[C], buc[C];
bool cmp(int a, int b) { return a > b;}
ll calc(int id, int lastpos, int now) { // 计算一个决策点的贡献
int num = (now - lastpos) / id;
if (num > (signed)bag[id].size() - 1) return -1;
return dp[id - 1][lastpos] + bag[id][num];
}
void solve(int id, int l, int r, int pl, int pr) {
int mid = (l + r) >> 1;
int pos = 0; ll maxv = 0;
for_up(i, pl , min(mid, pr)) { // 当前决策点可能的区间
ll val = calc(id, table[i], table[mid]);
if (val > maxv) maxv = val, pos = i; // 记录最大权值和决策点
}
if(l == r) { // 如果已经到达一个节点就更新答案
dp[id][table[l]] = maxv;
return;
}
// 因为决策单调 所以决策点可以进行划分求解
// 总复杂度是有保证的
solve(id, l, mid, pl, pos);
solve(id, mid + 1, r, pos, pr);
}
int main() {
memset(dp, 0, sizeof(dp));
Read(n), Read(k);
int maxc = 0;
for_up(i, 1, n) {
Read(c[i]), Read(v[i]);
buc[c[i]].push_back(v[i]);
maxc = max(maxc, c[i]);
}
for_up(i, 1, maxc) {
sort(buc[i].begin(), buc[i].end(), cmp);
bag[i].push_back(0);
ll now = 0;
for_vector(j, buc[i]) {
now += buc[i][j];
bag[i].push_back(now);
}
}
for_up(i, 1, maxc) {// 考虑单个售价是小于等于i的物品
for_up(j, 0, i - 1) {// 考虑对mod i余j的所有转移
table[ind = 1] = j;
while (table[ind] + i <= k) {
table[ind + 1] = table[ind] + i;
++ind;
}
solve(i, 1, ind, 1, ind);// 分治求解
}
}
for_up(i, 1, k) {
Write(dp[maxc][i]);
putchar(' ');
}
return 0;
}

LOJ6039. 「雅礼集训 2017 Day5」珠宝【决策单调性优化DP】【分治】【思维好题】的更多相关文章

  1. [LOJ#6039].「雅礼集训 2017 Day5」珠宝[决策单调性]

    题意 题目链接 分析 注意到本题的 \(C\) 很小,考虑定义一个和 \(C\) 有关的状态. 记 \(f(x,j)\) 表示考虑到了价格为 \(x\) 的物品,一共花费了 \(j\) 元的最大收益. ...

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

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

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

    题目描述 Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠宝,但可惜的是只能现金支付,Miranda 十分纠结究竟要带多少的现金,假如现金带多了,就会比较危险,假如带少了,看到想买的右 ...

  4. @loj - 6039@ 「雅礼集训 2017 Day5」珠宝

    目录 @description@ @solution@ @accpeted code@ @details@ @description@ Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠 ...

  5. loj #6039 「雅礼集训 2017 Day5」珠宝 分组背包 决策单调性优化

    LINK:珠宝 去年在某个oj上写过这道题 当时懵懂无知wa的不省人事 终于发现这个东西原来是有决策单调性的. 可以发现是一个01背包 但是过不了 冷静分析 01背包的复杂度有下界 如果过不了说明必然 ...

  6. loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移

    $ \color{#0066ff}{ 题目描述 }$ 给出一个长度为 \(n\) 宽度为 \(1\) ,高度无限的水箱,有 \(n-1\) 个挡板将其分为 \(n\) 个 \(1 - 1\) 的小格, ...

  7. 「雅礼集训 2017 Day5」矩阵

    填坑填坑.. 感谢wwt耐心讲解啊.. 如果要看这篇题解建议从上往下读不要跳哦.. 30pts 把$A$和$C$看成$n$个$n$维向量,那$A_i$是否加入到$C_j$中就可以用$B_{i,j}$表 ...

  8. LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)

    题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...

  9. 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...

随机推荐

  1. Nagios安装完后status map,trends等页面访问出错之解决

    首先,可以进入/usr/local/nagios/sbin, [root@localhost sbin]# ldd statusmap.cgi linux-vdso.so. => (0x0000 ...

  2. invocationCount和invocationTimeOut

    这篇我们来学习下@Test中另外两个属性invocationCount和invocationTimeOut,前面我介绍了timOut这个属性,知道是超时监控的功能.同样,本篇两个属性和这个差不多,只不 ...

  3. OpenID 和 OAuth 的区别及第三方登录的安全隐患分析

    转自:http://itindex.net/detail/48552-openid-oauth-%E6%96%B9%E7%99%BB 发表时间:2014-03-13 19:09 | 作者:天梯梦 出处 ...

  4. 搞懂分布式技术11:分布式session解决方案与一致性hash

    搞懂分布式技术11:分布式session解决方案与一致性hash session一致性架构设计实践 原创: 58沈剑 架构师之路 2017-05-18 一.缘起 什么是session? 服务器为每个用 ...

  5. RMAN中format的参数

    (转自:http://blog.chinaunix.net/uid-23079711-id-2554290.html) format 的替换变量,注意大小写! 1.     %d --数据库的db_n ...

  6. Java 进阶7 并发优化 1 并行程序的设计模式

       本章重点介绍的是基于 Java并行程序开发以及优化的方法,对于多核的 CPU,传统的串行程序已经很好的发回了 CPU性能,此时如果想进一步提高程序的性能,就应该使用多线程并行的方式挖掘 CPU的 ...

  7. Idea_01_安装与激活

    一.前言 二.安装 1.下载 https://www.jetbrains.com/idea/ 2.安装 默认安装即可 三.激活 Idea激活有如下两种方式 Activation code Lisenc ...

  8. Tencent tinker 出现pre-verified crash

    异常类型:app运行时异常 手机型号:sumsung N9008 手机系统版本:android4.4.2 tinker版本: 1.8.1 gradle版本::2.3.3 是否使用热更新SDK: Tin ...

  9. 记用ajax网页跳转大坑——后台执行了,但是没有跳转

    搭建javaweb服务器的时候,把jsp文件放在WEB-INF目录下面,因为超链接不能所有只能通过拦截器,用do方法跳转 controller写的是对的: @Controller public cla ...

  10. 【dlbook】优化

    [神经网络优化的挑战] 一.病态: 虽然学习率很小,而且梯度大,但是由于Hessian阵的病态,二次项比一次项还要大,梯度下降事实上并不一定能下降,反而有可能上升.因此需要将学习率调低. 表现:梯度很 ...