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. setInterva()调用

    setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭.由 s ...

  2. python的os.urandom 的用途

    Python中os.urandom(n)的作用 随机产生n个字节(0-255)的字符串,可以作为随机加密key使用~ >>> index = os.urandom(2) >&g ...

  3. sqlserver存储过程杀掉数据库中死锁

    Create proc p_lockinfo      @kill_lock_spid bit=1, --是否杀掉死锁的进程,1 杀掉, 0 仅显示      @show_spid_if_nolock ...

  4. Nginx1.8 安装说明

    安装Nginx .安装pcre cd /usr/local/src mkdir /usr/local/pcre tar zxvf pcre-8.36.tar.gz cd pcre-8.36 ./con ...

  5. 【Raspberry Pi】 小问题汇总

    注: 此系列为自己之前所搭建网站内容. 目前入手树莓派2,将遇到的一些琐碎的问题记录在此. 1. 更改时区 查看日期命令:date 输入sudo dpkg-reconfigure tzdata后按提示 ...

  6. vue elementui二级联动下拉选项demo

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

  7. jersey实现跨服务器上传

    1.导入跨服务器上传文件jar文件 <dependency> <groupId>commons-io</groupId> <artifactId>com ...

  8. 【河南省第十一届ACM大学生程序设计竞赛-D】.求XF+闭包

       如何设计一个好的数据库不仅仅是一个理论研究问题,也是一个实际应用问题.在关系数据库中不满足规范化理论的数据库设计会存在冗余.插入异常.删除异常等现象. 设R(U)是一个关系模式,U={ A1,A ...

  9. L3-010. 是否完全二叉搜索树

    L3-010. 是否完全二叉搜索树 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 将一系列给定数字顺序插入一个初始为空的二叉搜 ...

  10. C++设计模式之-原型模式

    Prototype 模式也正是提供了自我复制的功能, 就是说新对象的创建可以通过已有对象进行创建.在 C++中,拷贝构造函数( Copy Constructor) 曾经是很对程序员的噩梦,浅层拷贝和深 ...