zoukankan      html  css  js  c++  java
  • CF1555 E. Boring Segments(线段树+双指针)

    Problem - 1555E - Codeforces

    题意:

    n条线段,每条线段有权值,m个点,如果存在一条线段同时覆盖了点a和点b,那么就可以从点a到点b

    选一些线段,要求可以通过选出的线段从点1到达点m

    问选出的线段的最小差值

    题意相当于问选出一些线段,这些线段覆盖了所有的点

    我们先把所有的线段按权值从小到大排序

    先求出最大权值最小的满足要求的线段权值,设为x

    然后我们逐渐增大x,满足要求的权值区间下界会随着x的增大而增大

    这就可以用双指针法,相当于固定了权值区间右端点求最小的权值区间左端点

    左右端点都是单调向右移动的

    如何判断当前选出的线段是否覆盖了所有的点?

    用线段树维护,叶节点的点i表示i和i+1之间是否被覆盖了

    线段树内维护区间覆盖次数的最小值即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 300001
    #define M 1000001
    
    struct node
    {
        int l,r,w;
    }e[N];
    
    int mi[M<<2],tag[M<<2];
    
    bool cmp(node p,node q)
    {
        return p.w<q.w;
    }
    
    void down(int k,int l,int mid,int r)
    {
        tag[k<<1]+=tag[k];
        tag[k<<1|1]+=tag[k];
        mi[k<<1]+=tag[k];
        mi[k<<1|1]+=tag[k];
        tag[k]=0;
    }
    
    void add(int k,int l,int r,int opl,int opr,int w)
    {
        if(l>=opl && r<=opr)
        {
            tag[k]+=w;
            mi[k]+=w;
            return;
        }
        int mid=l+r>>1;
        if(tag[k]) down(k,l,mid,r);
        if(opl<=mid) add(k<<1,l,mid,opl,opr,w);
        if(opr>mid) add(k<<1|1,mid+1,r,opl,opr,w);
        mi[k]=min(mi[k<<1],mi[k<<1|1]);
    }
    
    int query(int k,int l,int r,int opl,int opr)
    {
        if(l>=opl && r<=opr) return mi[k];
        int mid=l+r>>1;
        if(tag[k]) down(k,l,mid,r);
        if(opr<=mid) return query(k<<1,l,mid,opl,opr);
        if(opl>mid) return query(k<<1|1,mid+1,r,opl,opr);
        return min(query(k<<1,l,mid,opl,opr),query(k<<1|1,mid+1,r,opl,opr)); 
    }
    
    int main()
    {
        int n,m,ans=1e7;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].w);
        sort(e+1,e+n+1,cmp); 
        int r,l=1; 
        for(int i=1;i<=n;i=r)
        {
            r=i;
            while(r<=n && e[r].w==e[i].w) 
            {
                add(1,1,m-1,e[r].l,e[r].r-1,1);
                ++r;
            }
            while(l && query(1,1,m-1,e[l].l,e[l].r-1)>1) 
            {
                add(1,1,m-1,e[l].l,e[l].r-1,-1);
                ++l;
            }
            if(mi[1]) ans=min(ans,e[r-1].w-e[l].w);
        }
        printf("%d",ans);
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    dynamic_debug和pr_debug()打印_高通平台
    Linux内核中的数据结构杂记
    Binder杂记
    内核中读写文件
    记一次阿里云ECS中Docker容器内无法连接RDS内网地址的故障解决
    mac上使用sips命令快速裁剪、旋转、翻转图片
    最新Android手机导出ANR、tombstones文件
    Android日期格式控制—— DateUtils
    addr2line的用法
    Spring-Cloud 学习笔记-(6)Feign
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15323549.html
Copyright © 2011-2022 走看看