[BZOJ4653][NOI2016]区间 贪心+线段树】的更多相关文章

4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MB Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri.   对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 [li,ri] 的长度…
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后,答案是一段子序列.所以我们考虑枚举右端点,尺取法取右边的线段,去到可以满足条件时将左边的这条线段删除.现在就是要维护一个数据结构可以得到是否存在一个点被覆盖了\(m\)次,直接线段树维护每个点被覆盖多少次即可.就是线段树支持区间加和求区间单点最值. 1A掉了很舒爽代码 //@winlere #inc…
题目分析: 首先思考一个二分答案的做法.我们可以注意到答案具有单调性,所以可以二分答案. 假设当前二分的答案是$ k $.那么按照大小顺序插入每个区间,同时在末端删除会对答案产生影响的区间.这里不妨用线段树维护.这个做法在外国好像叫做two pointers. 如果某个时刻,线段树中有点大于等于$ m $,说明这个答案是合理的,可以向上二分.若全程没有点大于$ m $说明这个答案不合理,向下二分. 时间复杂度是$ O(nlognlogN) $的,会超时. 从这个方法入手,考虑如何优化.实际上,二…
传送门 将坐标离散化之后直接用尺取法(双指针)+线段树维护. 其实就是说只要目前所有点的被覆盖次数是大于等于m的就移动左指针删除区间更新答案,否则移动右指针加入区间更新答案. 话说忘记排序以及建树的时候参数带错是几个意思?? 代码: #include<bits/stdc++.h> #define N 500005 #define lc (p<<1) #define rc (p<<1|1) #define mid (T[p].l+T[p].r>>1) usin…
BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri. 对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值…
4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 621  Solved: 329[Submit][Status][Discuss] Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri.   对于一个合…
题目链接 emmm看起来好像无从下手, \(l_i,r_i\)这么大,肯定是要离散化的. 然后我们是选\(m\)个区间,我们先对这些区间按长度排个序也不影响. 排序后,设我们取的\(m\)个区间的编号是\(b_1,b_2,...,b_m\), 若\(b_m\)确定,我们肯定是要尽量使\(b_1,b_2,...,b_{m-1}\)尽量接近\(b_m\)的,这样可使代价最小. 所以,就可以尺取了. 定义两个指针\(l,r\),首先\(r\)指针不停右移覆盖一遍扫到的区间直到满足条件有一个点被连续覆盖…
题目 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri. 对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值. 求所有合法方案中最小的花费.如果不存在合法的方案,输出 −1. 输入格式 第一行包…
传送门 考虑将所有的区间按长度排序 考虑怎么判断点被多少区间覆盖,这个可以离散化之后用一棵权值线段树来搞 然后维护两个指针$l,r$,当被覆盖次数最多的点的覆盖次数小于$m$时不断右移$r$,在覆盖次数大于等于$m$时不断右移$l$,然后每一次用$len[r]-len[l]$更新答案,其中$len$表示该区间的长度 //minamoto #include<iostream> #include<cstdio> #include<algorithm> #define inf…
写得很好的题解 一眼过去很像是:排序,然后从前向后扫,有这个区间时插到树里,过去以后再删除.然后事实也是这样做的…… 具体起来: 1.如果考虑暴力的话,一种想法是枚举左端和右端要选取的区间(如果我们按长度排序的话),那么只要发现当前选取的这些从左到右的区间可以得到m及以上就可以了,没必要特地考虑具体选哪些,然后ans = min(ans, 右len - 左len)即可. 2.判断这些区间是否可行的方法是:出现一个区间就把区间内所有点+1,线段树维护最大值,所以segment[1].maxx >=…