描述

数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~10^18,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大。


分析

提供两种思路:

  1. 利用离散化. 因为这道题本来就是离散化的例题. 将点排序后依次赋值(1~2n, n为线段的条数), 再通过结构体里的信息将离散化后的点的坐标映射到线段上.

  2. 利用二分法直接DP. 看到题解里有二分两个字, 自己YY出一套二分的做法不过好像和题解里的不一样: 将线段按终点从小到大排序, 考虑线段i, 用 f[i][0] 记录不选 i 的最大权值和, f[i][1] 记录选择 i 的最大权值和. 那么显然有 f[i][0] = max{f[i-1][0], f[i-1][1]}. 然后二分 (upper_bound()) 查找最后一个可以接在 i 前的线段 j, 那么 f[i][1] = max{f[j][0], f[j][1]} + v[i].

    不过尴尬的是第二种方法WA了四个点…而且差了不是一个数量级…


代码

3791ms, 65MB

// 1. 离散化
#include <cstdio>
#include <algorithm>
using namespace std; typedef long long LL;
const int maxn = 1000000 + 10;LL f[maxn<<1];struct Line { int s, t, v;bool operator < (const Line& rhs) const {if(t != rhs.t) return t < rhs.t;if(s != rhs.s) return s < rhs.s;return v < rhs.v;}
}lines[maxn];struct Point {bool d;     // d=0 -> on left; d=1 -> on rightLL pos;     // previous positionint id, x;  // id of the line, current positionbool operator < (const Point& rhs) const {return pos < rhs.pos;}
}points[maxn<<1];int main() {int n;scanf("%d", &n);for(int i = 0; i < n; i++) {LL s, t;scanf("%lld%lld%d", &s, &t, &lines[i].v);points[i<<1] = (Point) {0, s, i};points[(i<<1)^1] = (Point) {1, t, i};}sort(points, points + 2*n);// discretizationint base = 0, cnt = 0;while(base < 2*n) {int cur = base;points[cur++].x = ++cnt;while(points[cur].pos == points[base].pos && cur < 2*n) points[cur++].x = cnt;base = cur;}for(int i = 0; i < 2*n; i++) {Point& P = points[i];if(P.d == 0) lines[P.id].s = P.x;else lines[P.id].t = P.x;}sort(lines, lines + n);LL ans = 0LL;for(int cur = 0, pre = 0; cur < n; cur++) {Line& L = lines[cur];if(L.t != pre) {for(int i = pre + 1; i <= L.t; i++) f[i] = f[pre];pre = L.t;}ans = max(ans, (f[L.t] = max(f[L.t], f[L.s] + L.v)));}printf("%lld\n", ans);return 0;
}

// 二分
#include <cstdio>
#include <algorithm>
using namespace std; typedef long long ll;
const int maxn = 1000000 + 10;ll f[maxn][2], t[maxn];struct Line { ll s, t, v;bool operator < (const Line& rhs) const {if(t != rhs.t) return t < rhs.t;if(v != rhs.v) return v > rhs.v;return s > rhs.s;}
}lines[maxn];int main() {int n;scanf("%d", &n);for(int i = 0; i < n; i++) {ll s, t, v;scanf("%lld%lld%lld", &s, &t, &v);lines[i] = (Line) {s, t, v};}sort(lines, lines + n);for(int i = 0; i < n; i++) t[i] = lines[i].t; // 用于二分查找 f[0][0] = 0; f[0][1] = lines[0].v;for(int i = 1; i < n; i++) {Line L = lines[i];f[i][0] = max(f[i-1][0], f[i-1][1]);int j = upper_bound(t, t + n, L.s) - t - 1;if(j >= 0) f[i][1] = max(f[j][0], f[j][1]) + L.v;else f[i][1] = L.v; // 前面没有可以和它拼接的线段 }printf("%d\n", max(f[n-1][0], f[n-1][1]));return 0;
}

[CODEVS 3037] 线段覆盖 5相关推荐

  1. CodeVS 3027 线段覆盖2(DP)

    题目大意: http://codevs.cn/problem/3027/ 源码: #include <iostream>using namespace std;struct {int x, ...

  2. 【codevs30123037】线段覆盖4、5,姗姗来迟

    3012 线段覆盖 4 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 数轴上有n条线段,线段的两端都是整数坐标, ...

  3. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  4. ACM公选课第五节贪心4.14-5.4补+第六节上贪心线段覆盖

    每一步都不从全局,找当下就好 特征(还有dp基础) 求解(比如最小生成树那个) 伪代码 就是每个房间的比例都不一样 要靠经验 事件序列问题(dp贪心经典题) 用贪心解,最先结束的,后面选最先结束且不重 ...

  5. P1803 凌乱的yyy / 线段覆盖

    P1803 凌乱的yyy / 线段覆盖 https://www.luogu.org/problemnew/show/P1803 提交 题目提供者 yyy2015c01 嘤嘤嘤 评测方式 云端评测 标签 ...

  6. [Codevs] 1082 线段树练习3

    1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的 ...

  7. 线段覆盖(洛谷P1803题题解,C++语言描述)

    题目要求 P1803题目链接 分析 这题是一个线段覆盖问题,但并不是很复杂,也是贪心思想. 想要尽可能放线段,不能重合(可以正好相交),那就可以每一次只关注右端点,尽可能地选择剩余未选的线段中右端点最 ...

  8. 【多题合集】线段覆盖1、2、3

    1214 线段覆盖 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 给定x轴上的N(N<100)条线段,每个线段由它的二 ...

  9. 1214线段覆盖问题——贪心法

    题目描述: 给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,--N.这些坐标都是区间(-999,999)的整数.有些线段之间会相互交叠或覆盖. ...

最新文章

  1. 第9件事 产品定位要解决的6个问题
  2. Sql面试题之三(难度:简单| 含答案)
  3. Cookie的小知识
  4. 对tableView三种计算动态行高方法的分析
  5. Servlet 3.0 新特性详解
  6. 宝塔面板怎么下载php,宝塔面板下怎么安装Mosquitto-php扩展
  7. Python eval 与 exec 函数区别 - Python零基础入门教程
  8. 算法题存档2020425
  9. 运维学python用不上_运维工程师为什么要学python?
  10. 电子工业出版社博文视点Open Party 新年聚会 圆满成功召开
  11. 移远EC20 R2.0 AT指令拨号流程
  12. Map集合Key 按照ASCII码从小到大(字典序)排序
  13. 视频教程-学matlab符号计算-Matlab
  14. Android设计UI界面
  15. 服务器如何装系统和数据库,中软系统服务器及数据库安装规范(含维护).pdf
  16. 6-13 折半查找 (15 分)
  17. 高度自律学习者的app
  18. 修一座安全的广厦,庇护赛博世界的流浪者
  19. python中参数前面加星号是什么意思_详解Python函数中参数带星号是什么意思
  20. 判断有向图中是否存在从vi到vj的路径

热门文章

  1. [云炬创业基础笔记]第一章创业环境测试10
  2. [云炬创业基础笔记]商业模式在现代创业中的重要性
  3. [云炬Python学习笔记] Python读取指定文件夹下的文件
  4. 谈大学教育2018-01-12
  5. 小微商户申请php,微信小微商户申请入驻 - osc_r8q2esik的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. WOR文件转换成GST文件
  7. 关于.NET中的Server push技术
  8. 计算机网络第四章-网络层复习笔记
  9. 使用汇编软件emu8086输出十次Hello World!
  10. Java对象容器——集合Set