zoukankan      html  css  js  c++  java
  • [UOJ #222][NOI2016]区间(线段树)

    Description

    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。

    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值

    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

    Solution

    对区间的长度排序,离散化,然后线段树维护每个点被覆盖过的次数,根据决策的单调性就可做了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define MAXN 500005
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m;
    int a[MAXN*2],cnt=0;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=x*10+c-'0';c=getchar();
        }
        return x*f;
    }
    struct Node1
    {
        int L,R,len;
    }d[MAXN];
    bool cmp(Node1 x,Node1 y)
    {
        return x.len<y.len; 
    }
    struct Node2
    {
        int l,r,tag,maxn;
    }t[MAXN*8];
    void pushdown(int idx)
    {
        if(t[idx].tag&&t[idx].l!=t[idx].r)
        {
            int tag=t[idx].tag;
            t[idx].tag=0;
            t[idx<<1].tag+=tag;
            t[idx<<1|1].tag+=tag;
            t[idx<<1].maxn+=tag;
            t[idx<<1|1].maxn+=tag;
        }
    }
    void update(int idx)
    {
        t[idx].maxn=max(t[idx<<1].maxn,t[idx<<1|1].maxn);
    }
    void build(int idx,int l,int r)
    {
        t[idx].l=l,t[idx].r=r,t[idx].maxn=t[idx].tag=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(idx<<1,l,mid);
        build(idx<<1|1,mid+1,r);
    }
    void add(int idx,int x,int y,int z)
    {
        
        if(x<=t[idx].l&&y>=t[idx].r)
        {
            t[idx].maxn+=z;
            t[idx].tag+=z;
            return;
        }
        pushdown(idx);
        int mid=(t[idx].l+t[idx].r)>>1;
        if(y<=mid)add(idx<<1,x,y,z);
        else if(x>mid)add(idx<<1|1,x,y,z);
        else add(idx<<1,x,y,z),add(idx<<1|1,x,y,z);
        update(idx);
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        {
            d[i].L=read(),d[i].R=read();
            a[++cnt]=d[i].L,a[++cnt]=d[i].R;
            d[i].len=d[i].R-d[i].L; 
        }
        sort(a+1,a+1+cnt);
        cnt=unique(a+1,a+1+cnt)-a-1;
        sort(d+1,d+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            d[i].L=lower_bound(a+1,a+1+cnt,d[i].L)-a;
            d[i].R=lower_bound(a+1,a+1+cnt,d[i].R)-a;
        }
        int ans=INF,top=0;
        build(1,1,cnt);
        for(int i=1;i<=n;i++)
        {
            while(top<n&&t[1].maxn<m)
            {
                ++top;
                add(1,d[top].L,d[top].R,1);
            }
            if(t[1].maxn>=m)ans=min(ans,d[top].len-d[i].len);
            add(1,d[i].L,d[i].R,-1);
        }
        if(ans==INF)printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    } 
  • 相关阅读:
    tableau prep 转置-pivot
    tabeau 画Slopegraph斜面图
    java栈
    java快速排序
    java冒泡排序
    java实现双向链表
    五、使用依赖注入取代硬连接资源(静态工厂、单例),也可用于构造方法、bulider模式
    转 String的不变性 immutable
    三、使用私有构造方法(公开成员属性或者公开静态工厂方法)或者枚举类实现singleton
    有状态对象和无状态对象
  • 原文地址:https://www.cnblogs.com/Zars19/p/6806481.html
Copyright © 2011-2022 走看看