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. 那些年java MD5加密字符编码的坑

    相信做过MD5加密的童鞋都遇到过字符编码的坑,一般加密出来的结果和其他人不一样都是字符编码不一致导致的,比如类文件的字符编码.浏览器的字符编码等和对方不一致,所以就需要转码统一字符. 以下是笔者转码过 ...

  2. 01_Storm体系概要

    1. Storm发展历史 Storm历史 1. 2010年12月,backtype公司Nathan,提出Storm的核心概念2. backtype, 提供数据分析,数据处理服务的一个公司3. 2011 ...

  3. spring @RequestMapping注解技巧

    @RequestMapping 是 Spring Web 应用程序中最常被用到的注解之一.这个注解会将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上. 下面我们看看,@Request ...

  4. Linux Shell参数替换

    Linux Shell参数替换 2013-06-03 10:01 by 轩脉刃, 1816 阅读, 0 评论, 收藏, 编辑 Bash中的符号的作用是参数替换,将参数名替换为参数所代表的值.对于 来说 ...

  5. awardRotate.js

    (function($) { var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCh ...

  6. UWP C# 调用 C++/CX

    创建一个UWP项目 然后创建一个通用C++运行时项目 右键点击C++项目,添加一个C++类 在头文件中定义一个类 #pragma once namespace ImageFactoryRT { pub ...

  7. 新男人八题---AStringGame

    终于完成进度男人1/8,为了这题学了sam= = 题意先有一个串,n个子串,两个人轮流每次在子串上加字符,要求加完后还是原串的子串,最后不能加的就是输者,求赢的人 解法:sam之后在构造的状态图上跑s ...

  8. 【Python】改变对象的字符串显示

    问题 改变对象实例的打印或显示输出,让它们更具可读性. 解决方案 要改变一个实例的字符串表示,可重新定义它的 __str__() 和 __repr__() 方法.例如: class Pair: def ...

  9. 022——VUE中remove()方法的使用:

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 抽奖小程序,js,canvas

    js写的网页抽奖小程序,先上截图 源码地址:https://github.com/xiachaoxulu/raffle