[NOI2016]区间

Description:

在数轴上有\(N\) 个闭区间 \([l_1,r_1],[l_2,r_2],...,[l_n,r_n]\) 。现在要从中选出\(M\) 个区间,使得这\(M\) 个区间共同包含至少一个位置。换句话说,就是使得存在一个 \(x\) ,使得对于每一个被选中的区间\([l_i,r_i]\) ,都有 \(l_i≤x≤r_i\)
对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间\([l_i,r_i]\) 的长度定义为\(r_i-l_i\) ,即等于它的右端点的值减去左端点的值。
求所有合法方案中最小的花费。如果不存在合法的方案,输出\(-1\)

Hint:

\(n\le 5*10^5\)

Solution:

水题,观察到\(Ans=min\{max_{len}-min_{len}(存在一个x覆盖>=m)\}\)

这种形式的式子就一定是双指针了

所以按长度排序,双指针维护一下条件,线段树判一下\(>=m\)就行了

数组开大点.....

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=4e6+5;
ll n,m,cnt,hd[mxn];

inline ll read() {
    char c=getchar(); ll x=0,f=1;
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}

struct ed {
    ll to,nxt;
}t[mxn<<1];

inline void add(ll u,ll v) {
    t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

ll inf=2e9;
ll tot,bd,ans=inf,b[mxn];
ll tr[mxn<<2],tag[mxn<<2];

struct I {
    ll l,r,len;
}q[mxn];

ll cmp(I x,I y) {
    return x.len<y.len;
}

void push_up(ll p) {
    tr[p]=max(tr[ls],tr[rs]);
}

void push_down(ll p,ll l,ll r) {
    if(tag[p]) {
        ll mid=(l+r)>>1;
        tag[ls]+=tag[p]; tag[rs]+=tag[p];
        tr[ls]+=tag[p];
        tr[rs]+=tag[p];
        tag[p]=0;
    }
}

void update(ll l,ll r,ll ql,ll qr,ll x,ll p) {
    if(ql<=l&&r<=qr) {
        tag[p]+=x;
        tr[p]+=x;
        return ;
    }
    ll mid=(l+r)>>1; push_down(p,l,r);
    if(ql<=mid) update(l,mid,ql,qr,x,ls);
    if(qr>mid) update(mid+1,r,ql,qr,x,rs);
    push_up(p);
}

int main()
{
    n=read(); m=read(); ll l,r,len;
    for(ll i=1;i<=n;++i) {
        l=read(),r=read(),len=r-l;
        q[i]=(I){l,r,len}; b[++tot]=l,b[++tot]=r;
    }
    sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1;
    for(ll i=1;i<=n;++i) 
        q[i].l=lower_bound(b+1,b+tot+1,q[i].l)-b,
        q[i].r=lower_bound(b+1,b+tot+1,q[i].r)-b,chkmax(bd,q[i].r);
    sort(q+1,q+n+1,cmp); ll pos=1; 
    for(ll i=1;i<=n;++i) {
        update(1,bd,q[i].l,q[i].r,1,1);
        if(tr[1]<m) continue ;
        else while(tr[1]>=m&&pos<=i) {
            chkmin(ans,q[i].len-q[pos].len);
            update(1,bd,q[pos].l,q[pos].r,-1,1); ++pos;
        }
    }
    if(ans!=inf) printf("%lld",ans);
    else puts("-1");
    return 0;
}

posted @ 2019-03-26 21:45  cloud_9  阅读(106)  评论(0编辑  收藏  举报