• 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
    ",ans==0x3f3f3f3f?-1:ans);
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    文件操作3
    文件操作2
    kubernetes快速应用入门
    kubeadm初始化kubernetes集群
    kubernetes基础概念
    变量
    字面值
    关键字
    标识符
    Ubuntu安装MySql5.7
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9255443.html
Copyright © 2020-2023  润新知