【BZOJ4653】【NOI2016】区间 [线段树]

区间

Time Limit: 60 Sec  Memory Limit: 256 MB
[Submit][Status][Discuss]

Description

  在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
  对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
  求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

Input

  第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n
  接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。

Output

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

Sample Input

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

Sample Output

  2

HINT

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

Main idea

  给定若干个区间,取出m个若这m个包含同一个位置则可以统计值,值为这m个中的最大区间长度减去最小区间长度,输出最小值。

Solution

  发现答案为最大区间长度减去最小区间长度,显然可以先按照长度排序,然后枚举左端点(即最小区间长度),中间小于最大区间长度的区间的加入 只会使得更可能满足条件 而不会影响答案,所以我们用r表示当前加入到了右端点r这个位置,r显然递增,则可以用r一直往后推到满足条件了更新答案,用线段树维护区间+1。因为l[i]与r[i]长度较大,但是发现非常长的长度是不会影响是否可以统计的(因为满足统计的条件只要符合个数>=m即可),所以我们可以对l和r离散化。

Code

  1 #include<iostream>  
  2 #include<algorithm>  
  3 #include<cstdio>  
  4 #include<cstring>  
  5 #include<cstdlib>  
  6 #include<cmath>  
  7 using namespace std;  
  8     
  9 const int ONE=1000001;
 10 const int INF=2147483640;
 11 
 12 int n,m;
 13 int Ans,res;
 14 int num,cnt;
 15 
 16 struct lisan
 17 {
 18         int pos;
 19         int value;
 20 }Q[ONE*2];
 21 
 22 struct point
 23 {
 24         int l,r;
 25         int value;
 26 }a[ONE];
 27 
 28 struct power
 29 {
 30         int value;
 31         int add;
 32 }Node[ONE*4];
 33 
 34 int cmp(const point &a,const point &b)
 35 {
 36         return a.value<b.value;
 37 }
 38 
 39 int rule(const lisan &a,const lisan &b)
 40 {
 41         return a.value<b.value;
 42 }
 43 
 44 void pushdown(int i)
 45 {
 46         if(Node[i].add)
 47         {
 48             Node[i*2].add+=Node[i].add;
 49             Node[i*2+1].add+=Node[i].add;
 50             Node[i*2].value+=Node[i].add;
 51             Node[i*2+1].value+=Node[i].add;
 52             Node[i].add=0;
 53         }
 54 }
 55 
 56 void Update(int i,int l,int r,int L,int R,int x)
 57 {
 58         if(L<=l && r<=R)
 59         {
 60             Node[i].add+=x;
 61             Node[i].value+=x;
 62             return;
 63         }
 64         pushdown(i);
 65         
 66         int mid=(l+r)/2;
 67         if(L<=mid) Update(i*2,l,mid,L,R,x);
 68         if(mid+1<=R) Update(i*2+1,mid+1,r,L,R,x);    
 69         Node[i].value=max(Node[i*2].value,Node[i*2+1].value);
 70 }
 71 
 72 int get() 
 73 { 
 74         int res,Q=1;    char c;
 75         while( (c=getchar())<48 || c>57)
 76         if(c=='-')Q=-1;
 77         if(Q) res=c-48; 
 78         while((c=getchar())>=48 && c<=57) 
 79         res=res*10+c-48; 
 80         return res*Q; 
 81 }
 82 
 83 void Getlisan()
 84 {
 85         for(int i=1;i<=n;i++)
 86         {
 87             Q[++num].value=a[i].l; Q[num].pos=num;
 88             Q[++num].value=a[i].r; Q[num].pos=num;
 89         }
 90         
 91         sort(Q+1,Q+num+1,rule);
 92         Q[0].value=-1;
 93         for(int i=1;i<=num;i++)
 94         {
 95             if(Q[i].value!=Q[i-1].value) cnt++;
 96             int x=(Q[i].pos+1)/2;
 97             if(Q[i].pos % 2) a[x].l=cnt;
 98             else a[x].r=cnt;
 99         }
100         
101         sort(a+1,a+n+1,cmp);
102 } 
103 
104 int main()
105 {      
106         n=get();    m=get();
107         for(int i=1;i<=n;i++)
108         {
109             a[i].l=get();    a[i].r=get();
110             a[i].l++;    a[i].r++; 
111             a[i].value=a[i].r-a[i].l;
112         }
113         Getlisan();
114         
115         int r=0;
116         Ans=INF;
117         for(int i=1;i<=n;i++)
118         {
119             for(;;)
120             {
121                 if(Node[1].value>=m || (r+1)>n) break;
122                 r++;
123                 Update(1,1,cnt,a[r].l,a[r].r,1);
124             }
125             if(Node[1].value>=m)
126             Ans=min(Ans,a[r].value-a[i].value);
127             
128             Update(1,1,cnt,a[i].l,a[i].r,-1);
129         }
130         
131         if(Ans==INF) printf("-1");
132         else printf("%d",Ans);
133 }
View Code

 

posted @ 2017-02-22 17:09  BearChild  阅读(198)  评论(0编辑  收藏  举报