[bzoj4653]区间

将所有区间按照长度排序,枚举最小长度和最大长度,然后判断区间内是否存在符合条件的m个区间
这个东西由于右端点单调递增,所以即:1.支持插入区间;2.支持删除区间;3.维护是否存在被m个区间覆盖的点
对于3操作,可以视为维护区间max,即区间加减和区间max,线段树即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 500005
 4 #define mid (l+r>>1)
 5 struct ji{
 6     int l,r,len;
 7     bool operator < (const ji &k)const{
 8         return len<k.len;
 9     }
10 }a[N];
11 int V,n,m,r,sum,ans,f[N*30],laz[N*30],ls[N*30],rs[N*30];
12 void update(int &k,int l,int r,int x,int y,int z){
13     if ((l>y)||(x>r))return;
14     if (!k)k=++V;
15     if ((x<=l)&&(r<=y)){
16         f[k]+=z;
17         laz[k]+=z;
18         return;
19     }
20     update(ls[k],l,mid,x,y,z);
21     update(rs[k],mid+1,r,x,y,z);
22     f[k]=max(f[ls[k]],f[rs[k]])+laz[k];
23 }
24 int main(){
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n;i++){
27         scanf("%d%d",&a[i].l,&a[i].r);
28         a[i].len=a[i].r-a[i].l;
29     }
30     ans=0x3f3f3f3f;
31     sort(a+1,a+n+1);
32     for(int i=1,j=1;i<=n;i++){
33         if ((i==1)||(a[i-1]<a[i])){
34             for(;j<=n;j++){
35                 if ((f[r]>=m)&&((j==1)||(a[j-1]<a[j])))break;
36                 update(r,0,1e9,a[j].l,a[j].r,1);
37             }
38             if (f[r]>=m)ans=min(ans,a[j-1].len-a[i].len);
39         }
40         update(r,0,1e9,a[i].l,a[i].r,-1);
41     }
42     if (ans==0x3f3f3f3f)ans=-1;
43     printf("%d",ans);
44 }
View Code

 

posted @ 2019-12-04 21:08  PYWBKTDA  阅读(165)  评论(0编辑  收藏  举报