博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
6367. 【NOIP2019模拟2019.9.25】工厂
阅读量:5293 次
发布时间:2019-06-14

本文共 1351 字,大约阅读时间需要 4 分钟。

题目大意

给你一堆区间,将这些区间分成特定的几个集合,使得每个集合中的所有区间的并不为空。

求最大的每组区间的交的长度之和。


思考历程

一开始就认为这绝对是\(DP\)……

试着找一些性质,结果找不出来……
没办法,只能打个简单的状压\(DP\)……


正解

首先有个很不显然的结论:

对于两个不重合的区间\(a\)\(b\),如果它们互相包含(即\(l_a\leq l_b<r_b\leq r_a\)),那么一定满足:

  1. \(a\)\(b\)同在一个组内。
  2. \(b\)在某个组内,而\(a\)单独为一组。

证明:

假设存在这样的情况:\(a\)与其它若干个区间为一组,\(b\)也和其它的区间(或者没有)为一组。
有个很显然的性质,一个区间集合的子集的答案肯定大于等于这个区间的答案。
因为区间交操作只会使得长度越来越小。
所以,如果在这时将\(a\)移到\(b\)的那一组,\(a\)原来的那一组不会更小;并且由于\(a\)包含\(b\),区间交是有交换律的,\(a\)\(b\)的交还是\(b\),所以\(b\)的那一组的答案不会变。
因此,这种情况是可以被替代的。

证明了这个结论之后就可以搞事情了。

首先,对于区间\(a\),如果它跟某个被它包含的\(b\)一组,那么它并不会有什么贡献;
如果它自己为一组,它才会有贡献,但是这会占掉一个集合的位置。
于是就可以分成两种区间:不包含其它任何区间的区间,和包含了至少一个区间的区间。分别记作\(B\)集合和\(A\)集合。
对于\(B\),如果将所有区间以左端点排序,显然它们的右端点也是有序的。
有了这个优美的性质,分组的时候就是连在一块的区间作为一组。因为这一组的贡献是最左边区间的右端点减去最右边的左端点,如果从连在一块的区间中挖出一个,贡献是不变的。而在这个分组中,很显然我们要在保证贡献最大的同时,消耗的\(B\)集合内的区间尽量多。
\(f_{i,j}\)为前\(i\)个区间,分成了\(j\)组的贡献。转移显然。
统计答案的时候枚举\(B\)区间分成了几组,对于剩下的还没有分的组,就在\(A\)集合中贪心地选择最大的几个即可。


代码

using namespace std;#include 
#include
#include
#define N 210int n,ns,nb,p;struct Range{ int l,r;} q[N],qs[N];int qb[N],sum[N];bool bz[N];inline bool cmps(Range a,Range b){return a.l
=0;--k){ if (qs[k+1].r<=qs[i].l) break; for (int j=0;j

总结

智商还是太低了……

见到区间问题时,要想想各种类似于单调性的问题……
比如包含之类的……

转载于:https://www.cnblogs.com/jz-597/p/11592931.html

你可能感兴趣的文章
Mybatis生成resulteMap时的注意事项
查看>>
jquery-jqzoom 插件 用例
查看>>
1007. Maximum Subsequence Sum (25)
查看>>
《算法》C++代码 快速排序
查看>>
iframe的父子层跨域 用了百度的postMessage()方法
查看>>
Js apply方法与call方法详解 附ES6新写法
查看>>
linux php全能环境一键安装,小白福利!
查看>>
图片生成缩略图
查看>>
关于Mysql select语句中拼接字符串的记录
查看>>
动态规划 例子与复杂度
查看>>
[BZOJ4567][SCOI2016]背单词(Trie+贪心)
查看>>
查看oracle数据库的连接数以及用户
查看>>
【数据结构】栈结构操作示例
查看>>
中建项目环境迁移说明
查看>>
三.野指针和free
查看>>
activemq5.14+zookeeper3.4.9实现高可用
查看>>
TCP/IP详解学习笔记(3)IP协议ARP协议和RARP协议
查看>>
简单【用户输入验证】
查看>>
学android:直接用jdk来helloworld
查看>>
python tkinter GUI绘制,以及点击更新显示图片
查看>>