「JSOI2010」挖宝藏
「JSOI2010」挖宝藏
传送门
由于题目中说道挖一个位置的前提是挖掉它上面的三个,以此类推可以发现,挖掉一个点就需要挖掉这个点往上的整个倒三角,那么也就会映射到 \(x\) 轴上的一段区间(可以发现这种映射关系是一一对应的),那么我们就可以用一段区间来代表一个宝藏。
然后我们就先把所有区间按照右端点递增其次左端点递增排序。
接着考虑 \(\text{DP}\) ,我们设 \(dp_i\) 表示前 \(i\) 个区间中强制选第 \(i\) 个区间的最大利润,
那么在枚举转移点 \(j\) 时就会出现 \(i\) ,\(j\) 有交的情况,就会有一部分代价被多算。
此外还有一种情况就是一个区间完全覆盖另一个的情况,这个时候如果我们选那个较大的区间肯定会顺带选了那个较小的,
因为此时那个较小区间的代价就不用算了,所以我们可以预处理出单选一个区间的最大利润(它自己的价值以及被它覆盖的所有区间的价值之和 - 它自己的代价),
但我们又会发现,转移时会出现 \(i\) , \(j\) 两个区间同时覆盖一个小区间,导致那个小区间的价值被算重的情况,
所以我们干脆对于两个区间有交的情况我们暴力地去算可能被算重的价值即可,
具体来说就是枚举到 \(i\) 的时候,维护一个指针指向我们需要计算的区间,因为这个指针只会右移,所以我们转移的复杂度还是 \(O(n)\) 的,总复杂度也就是 \(O(n^2)\) 的。
如果有不懂的可以结合代码理解,还可以画图自己研究研究。
参考代码:
#include <algorithm>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
}
const int _ = 1002;
int n, dp[_]; struct node { int l, r, p1, p2, c; } t[_];
inline bool cmp(const node& x, const node& y) { return x.r != y.r ? x.r < y.r : x.l < y.l; }
inline int calc(int l, int r) { return (r - l + 2) * (r - l + 2) / 4; }
int main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(n);
for (rg int x, y, p, i = 1; i <= n; ++i)
read(x), read(y), read(p), t[i] = (node) { x + y + 1, x - y - 1, p, 0, calc(x + y + 1, x - y - 1) };
for (rg int i = 1; i <= n; ++i)
for (rg int j = 1; j <= n; ++j)
if (t[i].l <= t[j].l && t[j].r <= t[i].r) t[i].p2 += t[j].p1;
sort(t + 1, t + n + 1, cmp);
for (rg int i = 1; i <= n; ++i) {
dp[i] = t[i].p2 - t[i].c;
int nxt = 1, sum = 0;
for (rg int j = 1; j < i; ++j) {
if (t[j].r < t[i].l) dp[i] = max(dp[i], dp[j] + t[i].p2 - t[i].c);
if (t[j].l < t[i].l && t[i].l <= t[j].r) {
while (nxt <= i && t[nxt].r <= t[j].r) {
if (t[nxt].l >= t[i].l) sum += t[nxt].p1; ++nxt;
}
dp[i] = max(dp[i], dp[j] + t[i].p2 - t[i].c - (sum - calc(t[i].l, t[j].r)));
}
}
}
int ans = 0;
for (rg int i = 0; i <= n; ++i) ans = max(ans, dp[i]);
printf("%d\n", ans);
return 0;
}
「JSOI2010」挖宝藏的更多相关文章
- 「JSOI2010」排名
「JSOI2010」排名 传送门 看到先后顺序限制和字典序,很容易想到拓扑排序 + 贪心. 考虑具体做法: 对于第一问: 我们开一个大根堆来代替队列,然后从大到小构造出各个元素的排名. 我们连边 \( ...
- 「JSOI2010」找零钱的洁癖
「JSOI2010」找零钱的洁癖 传送门 个人感觉很鬼的一道题... 首先我们观察到不同的数最多 \(50\) 个,于是考虑爆搜. 但是这样显然不太对啊,状态数太多了. 然后便出现了玄学操作: \(\ ...
- 「JSOI2010」旅行
「JSOI2010」旅行 传送门 比较妙的一道 \(\text{DP}\) 题,思维瓶颈应该就是如何确定状态. 首先将边按边权排序. 如果我们用 \(01\) 串来表示 \(m\) 条边是否在路径上, ...
- 【LOJ】 #2520. 「FJOI2018」所罗门王的宝藏
题解 发现似乎相当于问一个2000个元的方程组有没有解-- 然而我懵逼啊-- 发现当成图论,两个点之间连一条边,开始BFS,每个点的值赋成边权减另一个点的点权 如果一个环不合法那么肯定无解 代码 #i ...
- LG4171/BZOJ1823 「JSOI2010」满汉全席 2-SAT
问题描述 LG4171 BZOJ1823 题解 显然,每个评委对每个材料的满式/汉式要求是对\(n\)个元素的\(0,1\)取值限制. 显然想到\(\mathrm{2-SAT}\) 于是就可以切掉了. ...
- 「JSOI2010」满汉全席
前言 由于蒟蒻才刚开始学 \(\text{2-SAT}\),所以题解中有的地方可能不够精炼,望多包涵! 题目描述 题目意思很简单,标准的\(\text{2-SAT}\)问题模型.那么我们就先来介绍一下 ...
- 「BZOJ1924」「SDOI2010」 所驼门王的宝藏 tarjan + dp(DAG 最长路)
「BZOJ1924」[SDOI2010] 所驼门王的宝藏 tarjan + dp(DAG 最长路) -------------------------------------------------- ...
- 「NOIP2017」宝藏
「NOIP2017」宝藏 题解 博客阅读效果更佳 又到了一年一度NOIPCSP-S 赛前复习做真题的时间 于是就遇上了这道题 首先观察数据范围 \(1 \le n \le 12\) ,那么极大可能性是 ...
- loj #2037. 「SHOI2015」脑洞治疗仪
#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...
随机推荐
- const在C与C++中的区别
在C中,const不是常量,只能说是一个不能改变的变量(注意是变量),C编译器不能把const看成看成一个编译期间的常量,因为他在内存中有分配,C编译器不知道他在编译期间的值.所以不能作为数组定义时的 ...
- no module named系列问题解决
持续更新中~~~ 1.终端指令错误:no module named 'gdbm' 解决办法: sudo apt-get install python3.6-gdbm 2.终端无法定位软件包 解决办法: ...
- 「题解」「BZOJ-4668」冷战
题目 点这里 思路及代码 我们可以使用并查集的按秩合并(但是不要路径压缩). 两个集合被合并起来,连上的边的权值就设为当前时间. 然后我们可以发现,询问 \(j\) 与 \(k\) 何时联通,就是查询 ...
- SPI(Service Provider Interface)--通过接口获取服务
spi 现在已有实现 jdk 提供实现 dubbo里的spi实现 一.jdk实现 配置 定义接口 定义实现类 配置资源文件 classpath下创建(META-INF/services/接口全面:ME ...
- hackinglab 冒充登录用户
首先进入网页会发现 直接用bp进行抓包然后会发现一个字母是Login这个是登录的意思发现这个字母等于0我们大胆的猜测一下这个字母等于0代表的是没有登陆而如果这个字母是1或者是2的时候就是登录了然后我们 ...
- Springboot项目搭建(3)-shiro登录
shiro简述+实现简单登录:https://www.jianshu.com/p/7f724bec3dc3
- 【PAT甲级】1111 Online Map (30分)(dijkstra+路径记录)
题意: 输入两个正整数N和M(N<=500,M<=N^2),分别代表点数和边数.接着输入M行每行包括一条边的两个结点(0~N-1),这条路的长度和通过这条路所需要的时间.接着输入两个整数表 ...
- Jquery插件validate使用一则
jquery.validate是一个基于jquery的非常优秀的验证框架,可以通过它迅速验证一些常见的输入,并且可以自己扩充自己的验证方法. 主要功能有: 验证url,email,number,len ...
- python中 使用join()方法
使用join()方法 对各种数据类型中元的素进行合并拼接 "连接符".join(列表或元组或字符串或字典) 返回的是一个使用连接符进行拼接的字符串 如果对象是列表,元组,就是以一个 ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 B. so easy (unordered_map+并查集)
这题单用map过不了,太慢了,所以改用unordered_map,对于前面删除的点,把它的父亲改成,后面一位数的父亲,初始化的时候,map里是零,说明它的父亲就是它本身,最后输出答案的时候,输出每一位 ...