洛谷P1712 区间

题目描述

在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。

对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。

求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

输入输出格式

输入格式:

第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n

接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。

N<=500000,M<=200000,0≤li≤ri≤10^9

输出格式:

只有一行,包含一个正整数,即最小花费。

输入输出样例

输入样例#1:

6 3
3 5
1 2
3 4
2 2
1 5
1 4

输出样例#1:

2

说明

贪心 扫描 线段树

把区间按长度从小到大排序,依次加入。用线段树维护数轴上被覆盖的次数最多是多少,当大于m时,更新答案,并删掉最早加入的区间。

正确性显然。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 using namespace std;
 7 const int mxn=500020;
 8 int read(){
 9     int x=0,f=1;char ch=getchar();
10     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
11     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
12     return x*f;
13 }
14 struct node{
15     int l,r;
16     int val,mk;
17 }t[mxn<<3];
18 int rot,sz=0;
19 #define ls t[rt].l
20 #define rs t[rt].r
21 void pushup(int rt){
22     t[rt].val=max(t[ls].val,t[rs].val);return;
23 }
24 void PD(int rt){
25     if(t[rt].mk){
26         if(!ls)ls=++sz;
27         t[ls].val+=t[rt].mk;t[ls].mk+=t[rt].mk;
28         if(!rs)rs=++sz;
29         t[rs].val+=t[rt].mk;t[rs].mk+=t[rt].mk;
30         t[rt].mk=0;
31     }
32     return;
33 }
34 void update(int L,int R,int v,int l,int r,int &rt){
35     if(!rt)rt=++sz;
36     if(L<=l && r<=R){
37         t[rt].mk+=v; t[rt].val+=v; return;
38     }
39     PD(rt);
40     int mid=(l+r)>>1;
41     if(L<=mid)update(L,R,v,l,mid,ls);
42     if(R>mid)update(L,R,v,mid+1,r,rs);
43     pushup(rt);
44     return;
45 }
46 struct line{
47     int L,R;
48     int len;
49     bool operator < (const line &b)const{
50         return len<b.len;
51     }
52 }a[mxn];
53 int n,m,mx;
54 void solve(){
55     int i,j;int ans=0x3f3f3f3f;
56     int hd=1;
57     for(int i=1;i<=n;i++){
58         update(a[i].L,a[i].R,1,0,mx,rot);
59         while(hd<=i && t[rot].val>=m){
60 //            printf("hd:%d val:%d\n",hd,t[rot].val);
61             ans=min(ans,a[i].len-a[hd].len);
62             update(a[hd].L,a[hd].R,-1,0,mx,rot);
63             ++hd;
64         }
65 //        printf("i:%d hd:%d\n",i,hd);
66     }
67     if(ans==0x3f3f3f3f)ans=-1;
68     printf("%d\n",ans);
69     return;
70 }
71 int st[mxn<<1],top=0;
72 int main(){
73     int i,j;
74     n=read();m=read();
75     for(i=1;i<=n;i++){
76         a[i].L=read();a[i].R=read();
77         a[i].len=a[i].R-a[i].L+1;
78         st[++top]=a[i].L;st[++top]=a[i].R;
79         mx=(a[i].R>mx)?a[i].R:mx;
80     }
81     sort(st+1,st+top+1);
82     top=unique(st+1,st+top+1)-st-1;
83     for(i=1;i<=n;i++){
84         a[i].L=lower_bound(st+1,st+top+1,a[i].L)-st;
85         a[i].R=lower_bound(st+1,st+top+1,a[i].R)-st;
86     }
87     mx=top;
88     sort(a+1,a+n+1);
89     solve();
90     return 0;
91 }
时间: 2024-12-19 06:42:48

洛谷P1712 区间的相关文章

[Noi2016]区间 BZOJ4653 洛谷P1712 Loj#2086

额... 首先,看到这道题,第一想法就是二分答案+线段树... 兴高采烈的认为我一定能AC,之后发现n是500000... nlog^2=80%,亲测可过... 由于答案是求满足题意的最大长度-最小长度最小,那么我们可以考虑将区间按长度排序 之后,因为我们是需要最大最小,所以,我们必定选择在排完序的区间上取连续的一段是最优情况(起码不会比别的差) 因此,考虑双指针扫一下就可以了... 是不是很水? 由于懒得写离散化,一开始写的动态开点线段树,我*****什么鬼?mle?!256mb开不下! lo

洛谷——P2082 区间覆盖(加强版)

P2082 区间覆盖(加强版) 题目描述 已知有N个区间,每个区间的范围是[si,ti],请求出区间覆盖后的总长. 输入输出格式 输入格式: N s1 t1 s2 t2 …… sn tn 输出格式: 共一行,一个正整数,为覆盖后的区间总长. 输入输出样例 输入样例#1: 复制 3 1 100000 200001 1000000 100000000 100000001 输出样例#1: 复制 900002 说明 [数据范围] 对于40%的数据 N≤1000,0<Si<Ti≤10000 对于100%

洛谷P2879 [USACO07JAN]区间统计Tallest Cow

To 洛谷.2879 区间统计 题目描述 FJ's N (1 ≤ N ≤ 10,000) cows conveniently indexed 1..N are standing in a line. Each cow has a positive integer height (which is a bit of secret). You are told only the height H (1 ≤ H ≤ 1,000,000) of the tallest cow along with th

洛谷P2982 [USACO10FEB]慢下来Slowing down(线段树 DFS序 区间增减 单点查询)

To 洛谷.2982 慢下来Slowing down 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently numbered 1..N move from the barn to her private pasture. The pastures are organized as a tree, with the barn being on pasture 1. Exactly N-1 cow

洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array is [1 3 -1 -3 5 3 6 7], and k = 3. 输入输出格式 输入格式: 输入一共有两行,第一行为n,k. 第二行为n个数(<INT_MAX). 输出格式: 输出共两行,第一行为每次窗口滑动的最小值

洛谷P1063 能量项链(区间DP)(环形DP)

To 洛谷.1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量.如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m*r*n(M

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

洛谷 P2801 教主的魔法 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=2801 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的身高一开始都是不超过1000的正整数.教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W.(虽然L=R时并不

[题解]洛谷比赛『期末考后的休闲比赛2』

[前言] 这场比赛已经结束了有几天,但我各种忙,虽然AK但还是没来得及写题解.(我才不会告诉你我跑去学数据结构了) T1 区间方差 (就不贴题好了) 首先可以推公式(我们可以知道,线段树然而并不能通过初中学过的方差公式在log(L)内求出方差): (s2表示方差,L表示区间长度,xi表示区间的每一项,最后一个x上画了一根线表示这些数据的平均数) 用二项式定理完全平方公式可得: 再次展开: 另外,再代入以下这个 得到了: 然后继续吧.. 然后duang地一声合并同类项,于是我们得到了: 然后可以高