LOJ6039. 「雅礼集训 2017 Day5」珠宝【决策单调性优化DP】【分治】【思维好题】
懒得搬题面
简要题意: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】【分治】【思维好题】的更多相关文章
- [LOJ#6039].「雅礼集训 2017 Day5」珠宝[决策单调性]
题意 题目链接 分析 注意到本题的 \(C\) 很小,考虑定义一个和 \(C\) 有关的状态. 记 \(f(x,j)\) 表示考虑到了价格为 \(x\) 的物品,一共花费了 \(j\) 元的最大收益. ...
- [loj6039]「雅礼集训 2017 Day5」珠宝 dp+决策单调性+分治
https://loj.ac/problem/6039 我们设dp[i][j]表示考虑所有价值小于等于i的物品,带了j块钱的最大吸引力. 对于ci相同的物品,我们一定是从大到小选k个物品,又发现最大的 ...
- 「雅礼集训 2017 Day5」珠宝
题目描述 Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠宝,但可惜的是只能现金支付,Miranda 十分纠结究竟要带多少的现金,假如现金带多了,就会比较危险,假如带少了,看到想买的右 ...
- @loj - 6039@ 「雅礼集训 2017 Day5」珠宝
目录 @description@ @solution@ @accpeted code@ @details@ @description@ Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠 ...
- loj #6039 「雅礼集训 2017 Day5」珠宝 分组背包 决策单调性优化
LINK:珠宝 去年在某个oj上写过这道题 当时懵懂无知wa的不省人事 终于发现这个东西原来是有决策单调性的. 可以发现是一个01背包 但是过不了 冷静分析 01背包的复杂度有下界 如果过不了说明必然 ...
- loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移
$ \color{#0066ff}{ 题目描述 }$ 给出一个长度为 \(n\) 宽度为 \(1\) ,高度无限的水箱,有 \(n-1\) 个挡板将其分为 \(n\) 个 \(1 - 1\) 的小格, ...
- 「雅礼集训 2017 Day5」矩阵
填坑填坑.. 感谢wwt耐心讲解啊.. 如果要看这篇题解建议从上往下读不要跳哦.. 30pts 把$A$和$C$看成$n$个$n$维向量,那$A_i$是否加入到$C_j$中就可以用$B_{i,j}$表 ...
- LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)
题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...
- 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...
随机推荐
- 08_MySQL DQL_SQL99标准中的多表查询(内连接)
# sql99语法/*语法: select 查询列表 from 表1 别名 [连接类型] join 表2 别名 on 连接条件 [where 筛选条件] [group by 分组] [having 分 ...
- 01_MySQL DQL_基础查询
DQL,Data Query Language,数据查询 # 基础查询/*语法:select 查询列表 from 表名: 特点:1.查询列表可以是:表中的字段,常量值.表达式.函数,也可以是多个组合2 ...
- hadoop安装时报错 /usr/local/hadoop-2.6.0-stable/hadoop-2.6.0-src/hadoop-hdfs-project/hadoop-hdfs/target/findbugsXml.xml does not exist
安装时报错:Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.7:run (site) on project ...
- vector的坑——C++primer练习6.33总结
说来惭愧,一道简单的对vector递归的题目写了一个多小时,最后还是请教了大神才改出来. 首先贴上原代码: void return_vector(vector<int>::iterator ...
- IE类兼容一
X-UA-Compatible是自从IE8新加的一个设置,对于IE8以下的浏览器是不识别的.通过在meta中设置X-UA-Compatible的值,可以指定网页的兼容性模式设置. 在网页中指定的模式优 ...
- 《Think in Java》(十七)容器深入研究
阿西吧,这一章好长啊,感觉看了快一个月了吧!JDK 自带的容器框架真是很好很强大啊,这一章看得有点蒙蒙的,接下来还得去看看官方文档啊!
- mysql 查看表信息
desc 表名; 查看表结构信息 show create table 表名; 查询建表详细信息 select COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT from i ...
- 如何在Ubuntu Linux上安装Oracle Java
不错文档,希望地址永久可用,url:http://zh.wikihow.com/%E5%9C%A8Ubuntu-Linux%E4%B8%8A%E5%AE%89%E8%A3%85Oracle-Java
- CodeForces - 91B单调队列
有一个数列,对于每一个数,求比它小的在他右边距离他最远的那个数和他的距离 用单调队列做,维护单调队列时可采用如下方法,对于每一个数,如果队列中没有数,则加入队列,如果队列头的数比当前数大,则舍弃该数 ...
- 大白话,讲编程之《ES6系列连载》汇总
如果你经历过2,3年前的前端开发,你一定感受过兼容IE6,7的痛苦,一定用过网页三剑客的dreamweaver编写html,面试的时候面试官一定会问你:会用PS切图吗? 刚开始的时候你发现,web前端 ...