zoukankan      html  css  js  c++  java
  • [Noi2016]区间

    来自FallDream的博客,未经允许,请勿转载,谢谢

    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。
    n<=500000 m<=200000
     
    考虑离散之后按照长度排序,从小到大加入线段,用线段树维护一下被覆盖最多次的点覆盖了多少次。每当这个次数大等于m,就让没用的线段全部出队,并且统计答案。
    复杂度nlogn
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define MN 500000
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9')  ch = getchar();
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x;
    }
    
    struct Node{int l,r,val,x;}T[MN*8+5];
    struct seg{int l,r,len;}s[MN+5];
    int cnt=0,n,m,p[MN*2+5],tot=1,ans=INF;
    bool cmp(seg x,seg y){return x.len<y.len;}
    
    void build(int x,int l,int r)
    {
        if((T[x].l=l)==(T[x].r=r)) return;
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);    
    }
    inline void mark(int x,int ad){T[x].x+=ad;T[x].val+=ad;}
    inline void pushdown(int x){mark(x<<1,T[x].val);mark(x<<1|1,T[x].val);T[x].val=0;}
    void Modify(int x,int l,int r,int ad)
    {
        if(T[x].l==l&&T[x].r==r) {mark(x,ad);return;}    
        if(T[x].val) pushdown(x);
        int mid=T[x].l+T[x].r>>1;
        if(r<=mid) Modify(x<<1,l,r,ad);
        else if(l>mid) Modify(x<<1|1,l,r,ad);
        else Modify(x<<1,l,mid,ad),Modify(x<<1|1,mid+1,r,ad); 
        T[x].x=max(T[x<<1].x,T[x<<1|1].x); 
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;++i) p[++cnt]=s[i].l=read(),p[++cnt]=s[i].r=read(),s[i].len=s[i].r-s[i].l;
        sort(s+1,s+n+1,cmp);sort(p+1,p+cnt+1);
        for(int i=2;i<=cnt;++i) if(p[i]!=p[i-1]) p[++tot]=p[i];
        for(int i=1;i<=n;++i) 
            s[i].l=lower_bound(p+1,p+tot+1,s[i].l)-p,
            s[i].r=lower_bound(p+1,p+tot+1,s[i].r)-p;
        build(1,1,tot);
        for(int i=1,j=0;i<=n;++i)
        {
            Modify(1,s[i].l,s[i].r,1);
            if(T[1].x>=m)
            {    
                for(;T[1].x==m;)++j,Modify(1,s[j].l,s[j].r,-1);
                ans=min(ans,s[i].len-s[j].len);
            }
        }
        printf("%d
    ",ans==INF?-1:ans);
        return 0;
    }
  • 相关阅读:
    Ymodem协议(参考STM32)
    嵌入式 Linux 对内存的直接读写(devmem)
    四则运算表达式分解,前中后缀表达式(栈的应用)
    I2C总线的仲裁机制
    用例图【图7】--☆
    顺序图【6】--☆☆
    部署图【图5】--☆
    组件图【图4】--☆
    活动图、泳道【图1】--☆☆
    Mybatis增删改查(CURD)
  • 原文地址:https://www.cnblogs.com/FallDream/p/Noi2016d2t1.html
Copyright © 2011-2022 走看看