luogu1712 区间 (尺取法+线段树)

先把区间按照长度从小到大排序,然后用尺取法来做

大概就是先一点一点把区间算上 直到某个点被覆盖了m次,然后一点一点把最前面的区间扔掉,直到没有点被覆盖m次,这样反复做(相当于是它选择的区间左右端点在那里摩擦)

判断有没有点被覆盖m次可以用线段树来做

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=500500;
 6 
 7 inline int read(){
 8     char c=getchar();int a=0;
 9     while(c<'0'||c>'9')  c=getchar();
10     while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}
11     return a;
12 }
13 
14 struct ST{
15     int x,id;bool isl;
16 }nd[maxn*2];
17 struct Line{
18     int l,r,siz;
19 }ln[maxn];
20 struct Node{
21     int l,r,num,laz;
22 }tr[maxn*4];
23 
24 int M,N;
25 
26 inline bool cmp1(ST a,ST b){return a.x<b.x;}
27 inline bool cmp2(Line a,Line b){return a.siz<b.siz;}
28 
29 void build(int i,int l,int r){
30     tr[i].l=l;tr[i].r=r;tr[i].num=tr[i].laz=0;
31     if(l>=r)  return;
32     int m=(l+r)>>1;build(i<<1,l,m);build(1+(i<<1),m+1,r);
33 }
34 
35 inline void pushdown(int i){
36     if(!tr[i].laz)  return;
37     if(tr[i].l==tr[i].r){tr[i].laz=0;return;}
38     int l=i<<1,r=(i<<1)+1;
39     tr[l].num+=tr[i].laz;tr[r].num+=tr[i].laz;
40     tr[l].laz+=tr[i].laz;tr[r].laz+=tr[i].laz;
41     tr[i].laz=0;return;    
42 }
43 inline void update(int i){if(tr[i].l<tr[i].r)tr[i].num=max(tr[i<<1].num,tr[(i<<1)+1].num);}
44 
45 void add(int i,int l,int r,int x){
46     if(tr[i].l==l&&tr[i].r==r){tr[i].num+=x;tr[i].laz+=x;return;}
47     int m=(tr[i].l+tr[i].r)>>1;pushdown(i);
48     if(l<=m)  add(i<<1,l,min(m,r),x);
49     if(r>m)  add((i<<1)+1,max(l,m+1),r,x);
50     update(i);
51 }
52 
53 int main(){
54     int i,j,k,ans=0x7fffffff;
55     N=read();M=read();
56     for(i=1;i<=N;i++){
57         ln[i].l=read();ln[i].r=read();ln[i].siz=ln[i].r-ln[i].l;
58         nd[i].x=ln[i].l;nd[i].id=i;nd[i].isl=1;
59         nd[i+N].x=ln[i].r;nd[i+N].id=i;nd[i+N].isl=0;
60     }sort(nd+1,nd+N*2+1,cmp1);
61     for(i=1,j=0;i<=N*2;i++){
62         if(nd[i].x!=nd[i-1].x)  j++;
63         if(nd[i].isl) ln[nd[i].id].l=j;
64         else  ln[nd[i].id].r=j;
65     }sort(ln+1,ln+N+1,cmp2);
66     
67     build(1,0,N*2);
68     for(i=1,j=0;i<=N;i++){
69         add(1,ln[i].l,ln[i].r,1);
70         if(tr[1].num>=M){
71             while(tr[1].num>=M){j++;add(1,ln[j].l,ln[j].r,-1);}
72             ans=min(ans,ln[i].siz-ln[j].siz);
73         }
74     }
75     if(ans!=0x7fffffff) printf("%d",ans);
76     else  printf("-1");
77 }

猜你喜欢

转载自www.cnblogs.com/Ressed/p/9858234.html
今日推荐