bzoj 5185 Lifeguards - 动态规划 - 贪心
题目传送门
传送点I
传送点II
题目大意
给定$n$个区间,问恰好删去其中$k$个,剩下的区间的并的最大总长度。
显然被包含的区间一定不优。再加上被包含的区间对计数不友好。直接把它删掉。
注意到题目说恰好,其实是骗人的。多删几个也不会影响(删太多了就有影响了)。
按照右端点排序,然后用$f[i][j]$表示考虑前$i$个区间,已经选了删掉$j$个。
考虑转移,第一种情况是第$i$个区间不选,直接通过$i - 1$转移。
第二种情况是要选$i$。然后要计算贡献。这时考虑上一个选择的是什么?
- 如果和第$i$个区间有相交,那么显然选择左端点最小的一个和当前区间相交的线段作为上一个。然后中间的线段全部删掉(因为它们被包含了。)。答案补上这个区间覆盖不到的但当前区间能够覆盖的地方。(如果上一个不是选的这个区间也无妨,因为这样一定没有下面这样的转移优)
- 否则从左端点最小的一个区间的前一个区间转移。答案加上当前区间长度。
Code
1 /** 2 * bzoj 3 * Problem#5185 4 * Accepted 5 * Time: 1140ms 6 * Memory: 43876k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 typedef class Segment { 13 public: 14 int l, r; 15 16 boolean operator < (Segment b) const { 17 if (r ^ b.r) return r < b.r; 18 return l < b.l; 19 } 20 }Segment; 21 22 const int N = 1e5 + 5, K = 105; 23 24 int n, m, k; 25 Segment* bs; 26 Segment* ss; 27 int f[N][K]; 28 29 inline void init() { 30 scanf("%d%d", &n, &k); 31 bs = new Segment[(n + 1)]; 32 ss = new Segment[(n + 1)]; 33 for (int i = 1; i <= n; i++) 34 scanf("%d%d", &bs[i].l, &bs[i].r); 35 } 36 37 inline void solve() { 38 sort(bs + 1, bs + n + 1); 39 for (int i = 1; i <= n; i++) { 40 if (i == 1 || bs[i].r != bs[i - 1].r) 41 ss[++m] = bs[i]; 42 else 43 k--; 44 } 45 46 int mil = (signed) (~0u >> 1); 47 n = 0; 48 for (int i = m; i; i--) { 49 if (ss[i].l < mil) 50 bs[++n] = ss[i], mil = ss[i].l; 51 else 52 k--; 53 } 54 sort(bs + 1, bs + n + 1); 55 k = max(k, 0); 56 memset(f, 0x80, sizeof(f[0]) * (m + 1)); 57 int p = 1; 58 f[0][0] = 0; 59 for (int i = 1; i <= n; i++) { 60 while (p <= i && bs[p].r < bs[i].l) 61 p++; 62 assert(p <= i); 63 for (int j = 1; j <= k; j++) 64 f[i][j] = max(f[i][j], f[i - 1][j - 1]); 65 f[i][k] = max(f[i][k], f[i - 1][k]); 66 67 for (int j = 0; j <= k; j++) { 68 int cj = min(j + i - p - 1, k); 69 if (p ^ i) 70 f[i][cj] = max(f[i][cj], f[p][j] + bs[i].r - bs[p].r); 71 cj = min(cj + 1, k); 72 f[i][cj] = max(f[i][cj], f[p - 1][j] + bs[i].r - bs[i].l); 73 } 74 } 75 printf("%d\n", f[n][k]); 76 } 77 78 int main() { 79 init(); 80 solve(); 81 return 0; 82 }
转载于:https://www.cnblogs.com/yyf0309/p/9451619.html
bzoj 5185 Lifeguards - 动态规划 - 贪心相关推荐
- 洛谷P1095守望者的逃离题解-伪动态规划/贪心
链接 题目描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上.为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很 ...
- 动态规划/贪心 - 无重叠区间
动态规划 dp[i]dp[i]dp[i]表示以区间iii结尾,可以共存最多的区间数量. dp[i]=max(dp[i],dp[j]+1)dp[i] = max(dp[i], dp[j] + 1)dp[ ...
- [剑指offer]面试题第[42]题[Leedcode][JAVA][第53题][最大子序和][动态规划][贪心][分治]
[问题描述][第53题][最大子序和][中等] 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和.示例:输入: [-2,1,-3,4,-1,2,1, ...
- LeetCode 1024. 视频拼接(动态规划/贪心)
文章目录 1. 题目 2. 解题 2.1 动态规划 2.2 贪心 1. 题目 你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事.这些片段可能有所重叠,也可能长度不一. 视频片段 ...
- [LeetCode刷题笔记]714 - 买卖股票的最佳时机含手续费(C++/Python3/Java/动态规划/贪心)
一.题目描述 给定一个整数数组 prices 和 整数 fee ,其中 prices[i] 表示第 i 天的股票价格,fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每笔交易都需要付 ...
- 算法——钻石金字塔(动态规划+贪心)
钻石金字塔 一.实验题目 矿工从金字塔顶部一直走到金字塔底部,每次只能走左下或者右下方向,每个区域内有一定数量的钻石,求矿工所能开采到的钻石的最大数量 (1)矿工并不事先知道金字塔的钻石分布,但是他可 ...
- 【44. 通配符匹配】动态规划 / 贪心
方法一: 动态规划 class Solution { public:bool isMatch(string s, string p) {int len_s=s.size();int len_p=p.s ...
- 动态规划/贪心总结(一)
最长递增子序列(一维) 子序列是可以不连续的. ,dp[i]是i位置以num[i]结尾的最长子序列长度 状态转移方程: dp[i]=max(dp[i],dp[j]+1),j<i且满足num[i] ...
- 【LeetCode】LeetCode之跳跃游戏——动态规划+贪心算法
[LeetCode]LeetCode之打家劫舍[暴力递归.动态规划.动态规划之优化空间的具体分析与实现] https://blog.csdn.net/Kevinnsm/article/details/ ...
最新文章
- python filter内置函数_python 内置函数filter
- 【git学习四】git基础之git为项目打标签
- ACM卡常处理办法(虽然我到现在没遇到)
- idea看更改过的代码_就是你把所有代码全写在一个类里的?
- 最好用的营养计算机软件,营养计算器(标准版)
- python中property函数_Python中的property()函数
- ROST情感分析的语法规则_《自然语言处理入门》12.依存句法分析--提取用户评论...
- 基于微信小程序的线上点餐平台
- 【三维CAD设计经验分享】CrownCAD设计:零件3D建模设计
- springboot基于webrtc和janus的视频会议流程图
- windows11中windows安全中心打不开的解决办法
- 在下载 chromium 源码时错误汇总
- cearte-react-app中craco中优雅引入svg【自定义宽、高、颜色,仅需5步】
- 『开源』源码在线阅读工具
- 用“心”迎接情人节,用另一种形式表达爱意
- android recovery 和reboot
- AE(After Effect) 自带抠像插件详解
- 入门级蓝牙遥控小车制作教程
- 搭建centos虚拟机
- GPRS模块为什么会低至十几元?我所经历的物联网模块国产化过程