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. Extjs前端框架解决了什么问题

    Extjs 作为一套企业级富客户端前端开发框架,主要解决了以下问题: 1.DOM Ext.Element: Ext.Element.get()快捷方式Ext.get(),只能以dom的id作为参数去获 ...

  2. Android真机调试——远程主机强迫关闭了一个现有的连接。

    以前用真机调试程序的时候,Android Studio 出现如下的错误 [2016-11-12 10:37:36 - DeviceMonitor] Adb connection Error:远程主机强 ...

  3. 【Demo】jQuery 轮播图简单动画效果

    功能实现: (1)设定图片称号的鼠标悬停事件: (2)在事件中利用自定义动画函数调整显示图片,并修改对应标号样式: (3)为图片显示区域设定鼠标悬停事件: (4)当鼠标停在该区域时,清除图片切换动画定 ...

  4. hdu4347The Closest M Points kdtree

    kdtree讲解: https://blog.csdn.net/qing101hua/article/details/53228668 https://blog.csdn.net/acdreamers ...

  5. 使用maven插件自动部署web应用至Docker容器的tomcat

    配置maven 在pom.xml加入 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 <plugins>     <plugin>         <gr ...

  6. C#/Java 程序员转GO/golang程序员笔记大全(day 01)

    前言: 整理一下学习 Go 语言的笔记,作为一名老程序,学习一名新的开发语言自然不需要像小白那样从 HelloWorld 看起. 简单整理一下 Go 的一些差异处,希望对大家学习 go 有点帮助,不正 ...

  7. mysql中一个字段根据另一字段的值分割为不同列

    1.数据结构如下: vehicleId mileage_type mileage 11AM6897           0 120 11AM6897           1 60 13AY9180 0 ...

  8. Ansible 小手册系列 十五(Blocks 分组)

    当我们想在满足一个条件下,执行多个任务时,就需要分组了.而不再每个任务都要用when. tasks: - block: - command: echo 1 - shell: echo 2 - raw: ...

  9. 发送垃圾邮件的僵尸网络——药物(多)、赌博、股票债券等广告+钓鱼邮件、恶意下载链接、勒索软件+推广加密货币、垃圾股票、色情网站(带宏的office文件、pdf等附件)

    卡巴斯基实验室<2017年Q2垃圾邮件与网络钓鱼分析报告> 米雪儿 2017-09-07 from:http://www.freebuf.com/articles/network/1465 ...

  10. CF 1A

    题解: n/a*m/a 都要向上取整 代码: #include<cstdio> #include<cmath> #include<cstring> #include ...