原题网址

https://codeforces.com/contest/1555/problem/E

题目大意

有n个区间。每个区间是[1,m]的子区间。从a可以一步走到b的充要条件是存在区间同时覆盖[a,b]。若n个区间中取出一些区间后,可以只通过被取出的区间从1走到m,则称这些被取出的区间组成的集合A是好的。每个区间有价值w,求一个好的集合A的所有元素中,最大价值与最小价值的差的最小值。

数据结构

线段树,支持以下两种操作:

  • 插入或删除区间
  • 查询当前区间集合是否为好的

若一个区间集是好的,则1.5,2.5,...,m-0.5都至少被一个区间覆盖,区间[a,b]可以覆盖a+0.5,...,b-0.5。所以我们可以将每个区间的右端点减一后再操作,线段树第a个元素表示a+0.5被多少个区间覆盖。这样只要查询线段树中[1,m-1]最小值是否为0,不为0即好的。

由于m较大,必须使用懒修改方法,每个节点增加lazy值(区别于真正的val值)。需要注意:

  • 访问某节点时,先进行push操作(将本节点lazy值转给val值,如果还有孩子,则lazy值传递给孩子,清空本节点lazy值),不管被查区间是多少(若l>r也要push,因为只要能递归到,就表示该点实际上表示了一个区间,需要把lazy值转给val值)。
  • 修改时,如果某个节点表示的区间全都要修改,只修改该节点lazy值,不递归。改完后必须进行push操作,把lazy值转成val并传递给孩子。
  • 递归返回时,将两个孩子的val组合成本节点的val。

解题思路

本题为最优化问题。显然尽可能选价值差较小的区间。

先将所有区间按价值排序。

用双指针维护一个范围,左指针为给定价值最小值时,右指针为最小的价值最大值。

枚举所有最小值,根据最小值指针和线段树查询结果移动最大值指针并更新最后答案(用最大值-最小值更新ans)。

我的代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int maxn = 300000;
constexpr int maxm = 2000000;
constexpr int inf = 0x7fffffff; struct seg {
int l, r, w;
}; bool operator<(const seg& a, const seg& b) { return a.w < b.w; } int n, m;
int tree[maxm * 4 + 2];
int lazy[maxm * 4 + 2];
seg segs[maxn + 4]; inline int lc(int i) { return i << 1; }
inline int rc(int i) { return (i << 1) + 1; } inline void pushdown(int i) {
lazy[lc(i)] += lazy[i], lazy[rc(i)] += lazy[i];
tree[lc(i)] += lazy[i], tree[rc(i)] += lazy[i];
lazy[i] = 0;
} int query(int s, int e, int l, int r, int i) {
if (s <= l && r <= e) return tree[i];
pushdown(i);
auto m = (l + r) >> 1;
int sum = inf;
if (s <= m) sum = min(query(s, e, l, m + 1, lc(i)), sum);
if (e >= m + 1) sum = min(query(s, e, m + 1, r, rc(i)), sum);
return sum;
} void update(int s, int e, int l, int r, int i, int val) {
if (s <= l && r <= e) {
lazy[i] += val, tree[i] += val;
return;
}
pushdown(i);
auto m = (l + r) >> 1;
if (s <= m) update(s, e, l, m, lc(i), val);
if (e >= m + 1) update(s, e, m + 1, r, rc(i), val);
tree[i] = min(tree[lc(i)], tree[rc(i)]);
} int main() {
scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) {
scanf("%d%d%d", &segs[i].l, &segs[i].r, &segs[i].w);
}
sort(segs + 1, segs + n + 1); int p2 = 1;
int ans = inf;
for (int p1 = 1; p1 <= n; ++p1) {
while (p2 < n + 1 && query(1, m - 1, 1, m - 1, 1) == 0) {
update(segs[p2].l, segs[p2].r - 1, 1, m - 1, 1, 1);
++p2;
}
if (query(1, m - 1, 1, m - 1, 1) == 0) break;
ans = min(ans, segs[p2 - 1].w - segs[p1].w);
update(segs[p1].l, segs[p1].r - 1, 1, m - 1, 1, -1);
}
printf("%d\n", ans);
return 0;
}

Educational Codeforces Round 112 E、Boring Segments的更多相关文章

  1. Educational Codeforces Round 6 F. Xors on Segments 暴力

    F. Xors on Segments 题目连接: http://www.codeforces.com/contest/620/problem/F Description You are given ...

  2. Educational Codeforces Round 41 B、C、D

    http://codeforces.com/contest/961 B题 可以将长度为k的连续区间转化成1 求最大和 解析 简单尺取 #include <stdio.h> #include ...

  3. Educational Codeforces round 78 A、B

    链接:https://codeforces.com/contest/1278 A:Shuffle Hashing 题意:对于一个字符串p可以执行一个"hash"操作,首先将p内的元 ...

  4. Educational Codeforces Round 13 A、B、C、D

    A. Johny Likes Numbers time limit per test 0.5 seconds memory limit per test 256 megabytes input sta ...

  5. Educational Codeforces Round 64 (Rated for Div. 2)题解

    Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...

  6. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  7. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  8. Educational Codeforces Round 58 (Rated for Div. 2) 题解

    Educational Codeforces Round 58 (Rated for Div. 2)  题目总链接:https://codeforces.com/contest/1101 A. Min ...

  9. Educational Codeforces Round 40千名记

    人生第二场codeforces.然而遇上了Education场这种东西 Educational Codeforces Round 40 下午先在家里睡了波觉,起来离开场还有10分钟. 但是突然想起来还 ...

  10. Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code

    Educational Codeforces Round 69 (Rated for Div. 2) E. Culture Code 题目链接 题意: 给出\(n\)个俄罗斯套娃,每个套娃都有一个\( ...

随机推荐

  1. [OpenCV实战]27 在OpenCV下使用forEach进行并行像素访问

    目录 1 Mat像素访问 1.1 使用at方法直接进行像素访问 1.2 使用指针进行像素访问 1.3 使用forEach方法进行像素访问 1.4 将forEach与C ++ 11 Lambda一起使用 ...

  2. ArcGIS Python判断数据是否存在

    判断是程序编写的一个基本的操作,也是增强程序稳定性的重要方式.在ArcPy处理数据时,要保证数据存在才能做后续的操作,为源GIS提示使用arcpy自带的Exists函数可判断要素类.表.数据集.sha ...

  3. 前端必备基础知识之--------原生JS发送Ajax请求

    原生JS发送Ajax请求 ajax({ type: 'POST', url: 'http://10.110.120.123:2222', // data: param, contentType: 'a ...

  4. 迁移学习(DIFEX)《Domain-invariant Feature Exploration for Domain Generalization》

    论文信息 论文标题:Domain-invariant Feature Exploration for Domain Generalization论文作者:Wang Lu, Jindong Wang, ...

  5. Thread和Runnable的区别-匿名内部类方式实现线程的创建

    Thread和Runnable的区别 如果一个类继承Thread ,则不适合资源共享.但是如果实现了Runable接口的话,则很容易的实现资源共享. 总结: 实现Runnable接口比继承Thread ...

  6. 打开sublime text3 弹出错误提示 Error trying to parse settings: Expected value inPackages\UserJSONsublime-settings:13:17

    问题:打开sublime text3 弹出错误提示 Error trying to parse settings: Expected value inPackages\UserJSONsublime- ...

  7. Nginx06 Rewrite

    1 简介 rewrite模块即ngx_http_rewrite_module模块,主要功能是改写请求URI,是Nginx默认安装的模块.rewrite模块会根据PCRE正则匹配重写URI,然后发起内部 ...

  8. Idea创建类模板方法模板

    参考https://blog.csdn.net/sdut406/article/details/81750858 写代码是少不了注释的,但是自带的注释就几个,所以使用注释模板添加自定义的注释是个非常好 ...

  9. Spring04-AOP(Debug查看执行流程)

    1 AOP的几个核心技术 AOP-面向切面编程的实现的核心技术:jvm运行期间对字节码进行修改或者动态生成新的字节码文件(asm技术). 2 AOP的几个核心概念 AOP在运行期间我们要对class文 ...

  10. Activiti01-基本介绍

    1.工作流的定义 工作流是将一组任务组织起来以完成某个有序的过程:定义了任务的触发顺序和触发条件,而且每个任务可以由一个或多个软件系统完成,也可以由一个或一组人完成, 还可以由一个或多个人与软件系统协 ...