P1712 [NOI2016]区间

题目描述

在数轴上有 NN 个闭区间 [l_1,r_1],[l_2,r_2],...,[l_n,r_n][l1,r1],[l2,r2],...,[ln,rn] 。现在要从中选出 MM 个区间,使得这 MM 个区间共同包含至少一个位置。换句话说,就是使得存在一个 xx ,使得对于每一个被选中的区间 [l_i,r_i][li,ri] ,都有 l_i≤x≤r_ilixri 。

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

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

输入输出格式

输入格式:

 

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

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

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 
6 3
3 5
1 2
3 4
2 2
1 5
1 4
输出样例#1: 
2

说明

Solution:

  今天PKU学长HRZ讲课,说到了本题,然后思路比较巧妙。

  方法就是对区间离散后,按原长度从小到大排序,然后用一个队列维护两个指针$l,r$,$O(n)$的去加入区间$s[l,r]+=1$,用线段树维护区间最大值,若区间最大值$\geq m$则从前往后把加入的区间删除,直到区间最大值刚好$< m$,那么用$l-1$所保存的长度和当前加入的区间长度差去更新答案,然后就没了。

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long 
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 #define lson l,m,rt<<1
 7 #define rson m+1,r,rt<<1|1
 8 using namespace std;
 9 const int N=800005;
10 int n,m,maxn[N<<3],add[N<<3],ans=0x7fffffff;
11 int l=1,r;
12 int *lst[N<<1],cnt,tot;
13 struct node{
14     int l,r,len;
15     bool operator<(const node &a)const{return len<a.len;}
16 }a[N],Q[N];
17 
18 il bool cmp(const int *a,const int *b) {return *a<*b;}
19 
20 il int gi(){
21     int a=0;char x=getchar();bool f=0;
22     while((x<'0'||x>'9')&&x!='-')x=getchar();
23     if(x=='-')x=getchar(),f=1;
24     while(x>='0'&&x<='9')a=(a<<1)+(a<<3)+x-48,x=getchar();
25     return f?-a:a;
26 }
27 
28 il void pushup(int rt){maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);}
29 
30 il void pushdown(int rt,int len){
31     if(add[rt]){
32         add[rt<<1]+=add[rt],
33         add[rt<<1|1]+=add[rt];
34         maxn[rt<<1]+=add[rt],
35         maxn[rt<<1|1]+=add[rt];
36         add[rt]=0;
37     }
38 }
39 
40 il void update(int L,int R,int k,int l,int r,int rt){
41     pushdown(rt,r-l+1);
42     if(L<=l&&R>=r){maxn[rt]+=k;add[rt]=k;return;}
43     int m=l+r>>1;
44     if(L<=m) update(L,R,k,lson);
45     if(R>m) update(L,R,k,rson);
46     pushup(rt);
47 }
48 
49 int main(){
50     n=gi(),m=gi();
51     For(i,1,n) a[i].l=gi(),a[i].r=gi(),a[i].len=a[i].r-a[i].l,lst[++cnt]=&a[i].l,lst[++cnt]=&a[i].r;
52     sort(lst+1,lst+cnt+1,cmp);
53     int k=-1;
54     For(i,1,cnt) {
55         if(*lst[i]!=k) k=*lst[i],*lst[i]=++tot;
56         else *lst[i]=tot;
57     }
58     sort(a+1,a+n+1);
59     For(i,1,n) {
60         Q[++r].l=a[i].l,Q[r].r=a[i].r,Q[r].len=a[i].len;
61         update(a[i].l,a[i].r,1,1,tot,1);
62         if(maxn[1]>=m){
63             while(l<=r&&maxn[1]>=m){
64                 update(Q[l].l,Q[l].r,-1,1,tot,1);
65                 l++;
66             }
67             if(maxn[1]<m) ans=min(a[i].len-Q[l-1].len,ans);
68         }
69     }
70     cout<<(ans==0x7fffffff?-1:ans);
71     return 0;
72 }

猜你喜欢

转载自www.cnblogs.com/five20/p/9351015.html