zoukankan      html  css  js  c++  java
  • BZOJ4653

    Portal

    Description

    给出数轴上的(n(nleq5 imes10^5))个闭区间,从中选出(m(mleq2 imes10^5))个,并且它们的交集不为空。一个合法方案的代价为所选区间中的最长长度减去最短长度,求最小代价。

    Solution

    将区间按长度由小到大排序。每次钦定区间(i)为最短区间,然后寻找(jgeq i)使得存在至少一个数被区间(i..j)中的(m)个覆盖,这可以用线段树实现。因为(j)是不退的,所以循环(i=1..n),每次向后寻找(j)即可。

    时间复杂度(O(nlogn))

    Code

    //[NOI2016]区间
    #include <algorithm>
    #include <cstdio>
    #include <queue>
    using namespace std;
    inline char gc()
    {
        static char now[1<<16],*s,*t;
        if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
        return *s++;
    }
    inline int read()
    {
        int x=0; char ch=gc();
        while(ch<'0'||'9'<ch) ch=gc();
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x;
    }
    int const N=1e6+10;
    int n,m; int n0,map[N];
    struct range{int L,R;} r[N>>1];
    bool cmpRng(range x,range y) {return x.R-x.L<y.R-y.L;}
    #define Ls (p<<1)
    #define Rs ((p<<1)|1)
    int rt; int maxV[N<<2],tag[N<<2];
    int L,R;
    void update(int p) {maxV[p]=max(maxV[Ls],maxV[Rs]);}
    void add(int p,int x) {maxV[p]+=x,tag[p]+=x;}
    void pushdw(int p) {if(tag[p]) add(Ls,tag[p]),add(Rs,tag[p]),tag[p]=0;}
    void ins(int p,int L0,int R0,int x)
    {
        if(L<=L0&&R0<=R) {add(p,x); return;}
        pushdw(p);
        int mid=L0+R0>>1;
        if(L<=mid) ins(Ls,L0,mid,x);
        if(mid<R) ins(Rs,mid+1,R0,x);
        update(p);
    }
    int query(int p,int L0,int R0)
    {
        if(L<=L0&&R0<=R) return maxV[p];
        pushdw(p);
        int mid=L0+R0>>1; int res=0;
        if(L<=mid) res=max(res,query(Ls,L0,mid));
        if(mid<R) res=max(res,query(Rs,mid+1,R0));
        return res;
    }
    int main()
    {   
        n=read(),m=read();
        for(int i=1;i<=n;i++) map[i*2-1]=r[i].L=read(),map[i*2]=r[i].R=read();
        sort(r+1,r+n+1,cmpRng);
        sort(map+1,map+n+n+1); n0=unique(map+1,map+n+n+1)-map-1;
        for(int i=1;i<=n;i++) r[i].L=lower_bound(map+1,map+n0+1,r[i].L)-map;
        for(int i=1;i<=n;i++) r[i].R=lower_bound(map+1,map+n0+1,r[i].R)-map;
        int ans=2e9; rt=1;
        for(int i=1,j=0;i<=n;i++)
        {
            while(true)
            {
                if(maxV[rt]>=m) break;
                if(++j>n) break;
                L=r[j].L,R=r[j].R,ins(rt,1,n0,1);
            }
            if(j>n) break;
            ans=min(ans,(map[r[j].R]-map[r[j].L])-(map[r[i].R]-map[r[i].L]));
            L=r[i].L,R=r[i].R; ins(rt,1,n0,-1);
        }
        if(ans==2e9) puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
    

    P.S.

    我菜死了...其实很简单的,也做过类似的题

  • 相关阅读:
    Centos 6下使用cmake编译安装MariaDB
    mysql索引
    mysql基础指令知识
    git/github安装与使用教程
    Linux目录结构详解
    static关键字的作用(修饰类、方法、变量、静态块)
    Java中重载(overloading)和重写(Overriding)的区别
    @PropertySources和@ImportReSources注解
    @ConfigurationProperties注解和@Value注解的区别
    Java中数组的定义,初始化和使用
  • 原文地址:https://www.cnblogs.com/VisJiao/p/BZOJ4653.html
Copyright © 2011-2022 走看看