LOJ#2086. 「NOI2016」区间

$n \leq 500000$个区间,从中挑出一些,使得至少有一个点被$m$个选中区间包含,且选中区间长度的极差最小。

区间题死脑筋晚期:把区间按左端点排序,然后右端点用个优先队列来弹,然后需要维护下标相差$m$的数字差的最值,可以在$n^2$的时间完美拿到签到题的60分。

求极差嘛,就是关注最大最小,不如把区间按长度升序,这样枚举两个区间时,可以把大小在他们之间的都加进线段树观察是否合法。然鹅,可以发现较长区间R往后枚举越来越长后,最优的较短区间L不会变小,也就是满足决策单调性,可以双指针搞定。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 //#include<math.h>
 5 //#include<set>
 6 //#include<queue>
 7 //#include<bitset>
 8 //#include<vector>
 9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12 
13 #define LL long long
14 int qread()
15 {
16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
18 }
19 
20 //Pay attention to '-' , LL and double of qread!!!!
21 
22 int n,m;
23 #define maxn 500011
24 struct Line{int x,y,v; bool operator < (const Line &b) const {return v<b.v;} }p[maxn];
25 
26 int lisa[maxn*2],li=0;
27 struct SMT
28 {
29     struct Node{int ls,rs,Max,add;}a[maxn<<2]; int size,n;
30     void up(int x) {a[x].Max=max(a[a[x].ls].Max,a[a[x].rs].Max);}
31     void build(int &x,int L,int R)
32     {
33         x=++size;
34         if (L==R) return;
35         int mid=(L+R)>>1;
36         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R);
37     }
38     void clear(int N) {n=N; size=0; int x; build(x,1,n);}
39     void addsingle(int x,int v) {a[x].add+=v; a[x].Max+=v;}
40     void down(int x) {if (a[x].add) {addsingle(a[x].ls,a[x].add); addsingle(a[x].rs,a[x].add); a[x].add=0;} }
41     int ql,qr,v;
42     void Add(int x,int L,int R)
43     {
44         if (ql<=L && R<=qr) {addsingle(x,v); return;}
45         down(x);
46         int mid=(L+R)>>1;
47         if (ql<=mid) Add(a[x].ls,L,mid);
48         if (qr>mid) Add(a[x].rs,mid+1,R);
49         up(x);
50     }
51     void add(int x,int y,int V) {ql=x; qr=y; v=V; Add(1,1,n);}
52 }t;
53 
54 int main()
55 {
56     n=qread(); m=qread();
57     for (int i=1;i<=n;i++)
58     {p[i].x=qread(); p[i].y=qread()+1; p[i].v=p[i].y-p[i].x-1; lisa[++li]=p[i].x; lisa[++li]=p[i].y;}
59     sort(p+1,p+1+n); sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1;
60     for (int i=1;i<=n;i++) p[i].x=lower_bound(lisa+1,lisa+1+li,p[i].x)-lisa,
61     p[i].y=lower_bound(lisa+1,lisa+1+li,p[i].y)-lisa;
62     
63     t.clear(li);
64     
65     int ans=0x3f3f3f3f;
66     for (int i=1,j=1;i<=n;i++)
67     {
68         t.add(p[i].x,p[i].y-1,1);
69         for (;j<=n;j++)
70         {
71             t.add(p[j].x,p[j].y-1,-1);
72             if (t.a[1].Max<m) {t.add(p[j].x,p[j].y-1,1); break;}
73         }
74         if (t.a[1].Max>=m) ans=min(ans,p[i].v-p[j].v);
75     }
76     printf("%d\n",ans==0x3f3f3f3f?-1:ans);
77     return 0;
78 }
View Code

 

posted @ 2018-07-02 19:36  Blue233333  阅读(192)  评论(0编辑  收藏  举报