• [NOI2016] 区间


    Solution

    答案贡献只与区间长度最大的和最小的有关,故长度介于它们之间的选不选无所谓。再贪一下,发现区间加得越多有可能会更优,那么一定要把所有能加的区间都加进去才最好。所以按长度排序之后,选了的区间一定是连续的一段。

    考虑一个朴素的暴力算法,我们枚举最大区间和最小区间,然后把其间的所有区间也加入,把对应位置打上标记。那么只需要知道有没有一个位置被打的标记次数大于等于 (m)。复杂度 (O(n^4))。线段树随便维护一下就能优化到 (O(n^3 log n)) ,但是好像没有什么用。

    发现枚举是连续的,不用每次全部重新统计。这样可以降到 (O(n^2 log n)),期望得分 60。

    瓶颈在于枚举端点。考虑固定右端点,那么最大的能使得标记大于等于 (m) 的点存在的左端点可以唯一确定。把右端点往右移动一格时,左端点也会跟着移动,而且我们发现左端点一定是单调的往右移动。这实际上就是一个 2-pointer 。那么复杂度就将为 (O(n log n)) ,期望得分 100。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define N 500007
    #define lid id<<1
    #define rid id<<1|1
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct Seg{
        int l,r,len;
        bool operator <(const Seg &X)const{return len<X.len;}
    }a[N];
    
    struct Node{
        int mx,tag,lf,rf;
    }t[(N*2)<<2];
    
    int n,m,sz;
    
    inline void update(int id){t[id].mx=max(t[lid].mx,t[rid].mx);}
    inline void Push(int id,int val){t[id].mx+=val,t[id].tag+=val;}
    inline void pushdown(int id){Push(lid,t[id].tag),Push(rid,t[id].tag),t[id].tag=0;}
    
    int L,R,V;
    
    #define Lf t[id].lf
    #define Rf t[id].rf
    
    void modify(int id){
        if(L<=Lf&&Rf<=R) Push(id,V);
        else{
            int mid=(Lf+Rf)>>1;
            if(t[id].tag) pushdown(id);
            if(L<=mid) modify(lid);
            if(R>mid) modify(rid);
            update(id);
        }
    }
    
    void build(int id,int lf,int rf){
        t[id].mx=t[id].tag=0;
        t[id].lf=lf,t[id].rf=rf;
        if(lf==rf) return ;
        int mid=(lf+rf)>>1;
        build(lid,lf,mid),build(rid,mid+1,rf);
    }
    
    inline bool check(int x){
        build(1,1,sz);
        for(int l=1,r=1;r<=n;r++){
            while(a[l].len+x<a[r].len)
                L=a[l].l,R=a[l].r,V=-1,modify(1),l++;
            L=a[r].l,R=a[r].r,V=1,modify(1);
            if(t[1].mx>=m) return 1;
        }
        return 0;
    }
    
    int X[N<<1];
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            a[i].l=read(),a[i].r=read(),a[i].len=a[i].r-a[i].l,
            X[(i<<1)-1]=a[i].l,X[i<<1]=a[i].r;
        sort(a+1,a+1+n),sort(X+1,X+1+2*n);
        sz=unique(X+1,X+1+2*n)-(X+1);
        for(int i=1;i<=n;i++)
            a[i].l=lower_bound(X+1,X+1+sz,a[i].l)-X,
            a[i].r=lower_bound(X+1,X+1+sz,a[i].r)-X;
        int l=1,ans=X[sz]+1;
        build(1,1,sz);
        for(int i=1;i<=n;i++){
            L=a[i].l,R=a[i].r,V=1,modify(1);
            while(l<i){
                L=a[l].l,R=a[l].r,V=-1,modify(1);
                if(t[1].mx>=m) l++;
                else{V=1,modify(1);break;}
            }
            if(t[1].mx>=m) ans=min(ans,a[i].len-a[l].len);    
        }
        printf("%d",ans==X[sz]+1? -1:ans);
    }
    
  • 相关阅读:
    Python神库分享之geoip2 IP定位库
    科普一下推荐引擎
    浏览器插件之王-Tampermonkey(油猴脚本)
    Swagger入门教程
    使用SonarQube+Eclipse来分析python代码
    什么是搜索引擎蜘蛛?
    让所有网站都提供API的Python库:Toapi
    如何提高自己的逻辑思维能力?
    推荐系统和搜索引擎的关系
    html 后台页面布局
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14528030.html
Copyright © 2020-2023  润新知