BZOJ4653 尺取法 + 线段树】的更多相关文章

https://www.lydsy.com/JudgeOnline/problem.php?id=4653 首先很容易想到离散之后排序,用线段树或者树状数组去维护. 问题在于按照什么排序,如果按照左端点右端点排序,线段树就需要维护最大值最小值和区间和等等信息,在区间和超过M之后最大值就变为了K大到最大的信息,不但麻烦而且难以下手. 所以想到直接按照区间长度排序,仅仅维护一个区间最值,代表这个区间里最大的点被覆盖了多少次,然后用一种尺取的思想,使得线段树里的最大值一值不超过M,如果超过了就在尾部开…
先把区间按照长度从小到大排序,然后用尺取法来做 大概就是先一点一点把区间算上 直到某个点被覆盖了m次,然后一点一点把最前面的区间扔掉,直到没有点被覆盖m次,这样反复做(相当于是它选择的区间左右端点在那里摩擦) 判断有没有点被覆盖m次可以用线段树来做 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ; inline int read(){ ; ') c=getchar(…
题目链接: C. Foe Pairs time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output   You are given a permutation p of length n. Also you are given m foe pairs (ai, bi) (1 ≤ ai, bi ≤ n, ai ≠ bi). Your task…
LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左到右加入线段 加到线段的每个端点的时候 将所有加入的线段 插到主席树里面 考虑判定当前ans合法. 每加入一条线段权值为v 那么意味着 权值在 v-ans这个权值区间中加1 且看一下之前是否存在相同权值的线段加入 更新其本身. 这样查一下全局最大值即可完成判定 实现起来非常繁琐 复杂度\(nlog^…
洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一个点被覆盖次数大于m 我们将覆盖这个点的区间升序排序: 则所选区间一定是排序后序列中的一个长度为m+1的连续子序列 证明很容易,取更远的点会使最大值更大从而使差值最大 我们可以从这个结论出发,再观察该题所求,符合尺取法的思路 我们考虑用尺取法求解 没了解尺取法的读者可以去自行了解一下 如何求解呢?…
题目传送门 区间 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: 107  Solved: 70[Submit][Status][Discuss] Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri. 对于一个合法的选…
题意 题目链接 Sol 按照dls的说法,一般这一类的题有两种思路,一种是枚举一个点\(M\),然后check它能否成为答案.但是对于此题来说好像不好搞 另一种思路是枚举最小的区间长度是多少,这样我们把所有区间按长度排序后可以二分出满足条件的最短的区间长度 观察后不难发现,较长区间的长度一定是随着短区间长度的增加而单调递增的. 直接用双指针维护即可. 判断是否可行也就是是否有一个点被覆盖了\(m\)次,离散化后线段树维护.. 经验: 该类问题的两种思路 最大值的单调性 #include<bits…
Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri. 对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值. 求所有合法方案中最小的花费.如果不存在合法的方案,输出 −1.…
传送门 将坐标离散化之后直接用尺取法(双指针)+线段树维护. 其实就是说只要目前所有点的被覆盖次数是大于等于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…
题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间,使得这 \(M\) 个区间共同包含至少一个位置.换句话说,就是使得存在一个 \(x\) ,使得对于每一个被选中的区间 \([l_i,r_i]\) ,都有 \(l_i≤x≤r_i\) . 对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 \([l_i,r_i]\) 的长度定义为 \(r_i-l_i\) ,即…
题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭区间,然后线段树的每一个节点表示一个半开半闭区间. 接着我们注意到需要求最小的花费,且这个花费只与选择的区间集合中的最大长度和最小长度有关. 这意味着如果最大长度和最小长度一定,我们显然是需要把中间长度的区间尽量的选择进去使答案不会变的更劣. 不妨把区间按长度排序,枚举每个最小长度区间,然后最大区间…
题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前花开的数量,放张图易理解: 还有一种做法用尺取法的思想,对暴力方法优化,对询问点排序后再扫描一遍,花开+1,花谢-1.详细看代码. 收获:一题收获很多:1. 降低复杂度可以用二分 2. 线段计数问题可以在端点标记1和-1 3. 离散化+线段树 终于会了:) (听说数据很水?) 代码1:离散化+线段树…
nekameleoni 区间查询和修改 给定N,K,M(N个整数序列,范围1~K,M次查询或修改) 如果是修改,则输入三个数,第一个数为1代表修改,第二个数为将N个数中第i个数做修改,第三个数为修改成这个数(例如1 3 5就是修改数组中第3个数,使之变为5) 如果是查询,则输入一个数2,查询N个数中包含1~K每一个数的最短连续子序列的长度 输入 第一行包含整数N.K和M(1 ≤ N,M ≤ 100000,1 ≤ K ≤ 50) 第二行输入N个数,用空格隔开,组成该数组 然后M行表示查询或修改 若…
题目链接 题目大意:给定$n$个区间$[l_i,r_i]$,选出$m$个区间使它们有一个共同的位置$x$,且使它们产生的费用最小.求最小费用.费用定义为最长的区间长度减去最短区间长度. ----------------- 因为区间顺序改动又不影响答案,我们不妨按照长度排个序.看到数据范围果断离散化. 思考一种最朴素的做法:将排好序的区间逐一加入数轴,看有没有一个点被覆盖的次数$\geq m$. 有的话就统计一下答案,然后将前面加入的数删掉,直到$<m$. 显然用到了尺取法.维护是否有一个点被覆盖…
正题 题目链接:https://www.luogu.com.cn/problem/P1712 题目大意 \(n\)个区间,求出其中\(m\)个区间使得它们有覆盖同一个点且最长区间长度减去最短长度最小. 解题思路 因为是最接近的\(m\)个,考虑一种叫尺取法的做法. 先把区间按照长度排序,每次加入一个区间直到满足有位置被覆盖不少于\(m\)次,然后统计答案后不断弹出末尾区间直到没有区间出现不少于\(m\)次. 用线段树维护就好了,懒得动态开点就写了个离散化. 时间复杂度\(O(n\log n)\)…
写得很好的题解 一眼过去很像是:排序,然后从前向后扫,有这个区间时插到树里,过去以后再删除.然后事实也是这样做的…… 具体起来: 1.如果考虑暴力的话,一种想法是枚举左端和右端要选取的区间(如果我们按长度排序的话),那么只要发现当前选取的这些从左到右的区间可以得到m及以上就可以了,没必要特地考虑具体选哪些,然后ans = min(ans, 右len - 左len)即可. 2.判断这些区间是否可行的方法是:出现一个区间就把区间内所有点+1,线段树维护最大值,所以segment[1].maxx >=…
不得不说,这也许会是一道长期在我的博客里作为“HARD”难度存在的题 这道题能很好的考验选手的思考能力,但本蒟蒻最后还是听了省队爷讲了之后才会...(默默面壁) 题目里,说对于每一个点,是用当前选出的M个里面,最长长度减去最短长度作为价值.也就是说:选择长度介于最长与最短之间的边,是对答案没有影响的.(本蒟蒻并没有想到这一点...) 所以由于这一点,我们可以先对于边的长度排序. 那么题目中提到的M,是“选中多余或等于M条边”,从这里就可以看出,我们只需要选定一个头和一个尾就好,由此可以看出,这个…
[BZOJ4653][NOI2016]区间(线段树) 题面 BZOJ 题解 \(NOI\)良心送分题?? 既然是最大长度减去最小长度 莫名想到那道反复减边求最小生成树 从而求出最小的比值 所以这题的套路是一样的 按照长度排序之后 依次加入 如果当前有被覆盖了超过\(m\)次的点 就从前面开始,依次把线段拿走 每次更新一下答案就好啦 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstr…
题目大意 数轴上有\(n\)个闭区间\([l_1,r_1],[l_2,r_2],\ldots,[l_n,r_n]\),你要选出\(m\)个区间,使得存在一个\(x\),对于每个选出的区间\([l_i,r_i]\)都有\(x\in[l_i,r_i]\). 一个方案的代价是最长区间长度减去最短区间长度. 求最小的代价. 无解输出\(-1\). \(m\leq n\leq 500000\) 题解 就是选出\(m\)个区间,包含同一个点. 如果多选一些区间,那么答案不会变小. 问题转化成选一些区间,使得…
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3141 题意 一个1到n的排列,每次随机删除一个,问删除前的逆序数 思路 综合考虑,对每个数点,令value为值,pos为位置,time为出现时间(总时间-消失时间),明显是统计value1 > value2, pos1 < pos2, time1 < time2的个…
题目链接 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\)指针不停右移覆盖一遍扫到的区间直到满足条件有一个点被连续覆盖…
[BZOJ4653][Noi2016]区间 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri. 对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值. 求所有合法方案中最小…
题目分析: 首先思考一个二分答案的做法.我们可以注意到答案具有单调性,所以可以二分答案. 假设当前二分的答案是$ k $.那么按照大小顺序插入每个区间,同时在末端删除会对答案产生影响的区间.这里不妨用线段树维护.这个做法在外国好像叫做two pointers. 如果某个时刻,线段树中有点大于等于$ m $,说明这个答案是合理的,可以向上二分.若全程没有点大于$ m $说明这个答案不合理,向下二分. 时间复杂度是$ O(nlognlogN) $的,会超时. 从这个方法入手,考虑如何优化.实际上,二…
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] 的长度…
题意:给一个数列,按如下公式求和. 分析:场上做的时候,傻傻以为是线段树,也没想出题者为啥出log2,就是S(i,j) 的二进制表示的位数.只能说我做题依旧太死板,让求和就按规矩求和,多考虑一下就能发现这个题目应该是另想办法解决的,类似于改代码的题目,直接告诉你C++代码,让你从TLE改成AC,其实真正让你改的是算法,全身都要变. 看了题解,终于明白这道题目的正解算法: 因为S(i,j)的位数在一定范围内是一样的,所以我们可以枚举位数1~35(顶多是2^34),怎么计算(i+j)?继续枚举起点k…
给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成为一段长度为n的数列 现在mm想要从这数列中选出一个连续的区间,要求这个区间的max-min<=m 输出最长的区间 做了一个下午 思路: 分成2个部分: 1.求出数列,即对于一棵树,求出每一个节点能到达的最远距离 2.对于这段数列,选出一个区间,使得区间的max-min<=m,并且使得区间长度尽量…
1553: Good subsequence Time Limit: 2 Sec  Memory Limit: 256 MBSubmit: 794  Solved: 287[Submit][Status][Web Board] Description Give you a sequence of n numbers, and a number k you should find the max length of Good subsequence. Good subsequence is a c…
P1712 [NOI2016]区间 题意 题目描述 在数轴上有 \(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) .现在要从中选出 \(M\) 个区间,使得这 \(M\) 个区间共同包含至少一个位置.换句话说,就是使得存在一个 \(x\) ,使得对于每一个被选中的区间 \([l_i,r_i]\) ,都有 \(l_i \leq x \leq r_i\) . 对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度.区间 \([l…
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后,答案是一段子序列.所以我们考虑枚举右端点,尺取法取右边的线段,去到可以满足条件时将左边的这条线段删除.现在就是要维护一个数据结构可以得到是否存在一个点被覆盖了\(m\)次,直接线段树维护每个点被覆盖多少次即可.就是线段树支持区间加和求区间单点最值. 1A掉了很舒爽代码 //@winlere #inc…