zoukankan      html  css  js  c++  java
  • CF 1555 E. Boring Segments

    E. Boring Segments

    题目大意

    给定一个数轴,(1 o m),以及(m)个线段的(l_i, r_i, w_i),为线段的左端点,右端点,以及价值。

    现在要求选择一些线段,使得能够从数轴上的(1)出发,沿着线段走,能够到达(m)

    代价是选择的线段的价值的极差。

    问最小的代价值。

    解题思路

    我们将线段按照价值从小到大排序,然后依次枚举价值最小的线段。

    然后不断地往右取线段,直到能够从(1)走到(m),此时即为一个答案。

    随着价值最小的线段不断右移,价值最大的线段也在不断右移,所谓的双指针法。

    此时只要考虑如何维护选择的线段覆盖的信息。

    由于(mleq 10^6),维护每个数字被线段覆盖的次数,用线段树维护即可,区间加法和区间最小值。

    注意到仍存在一点问题,即如果一条线段覆盖(1,2,3),另一条线段覆盖(4,5),此时从(1)不能达到(5),我们还需要一条线段覆盖(3,4)也就是说3,4之间再插入一个点

    因此将所有坐标都乘以(2),为每个数字之间都插入一个点,然后再区间加法和区间查询最小值即可。

    神奇的代码
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N = 2e6 + 8;
    
    class Segment{
    #define lson root << 1
    #define rson root << 1 | 1
    
        int minn[N << 2];
        int lazy[N << 2];
    
        public:
    
        void pushdown(int root){
            if (lazy[root] == 0)
                return;
            minn[lson] += lazy[root];
            minn[rson] += lazy[root];
            lazy[lson] += lazy[root];
            lazy[rson] += lazy[root];
            lazy[root] = 0;
        }
    
        void update(int root, int l, int r, int ll, int rr, int val){
            if (ll <= l && r <= rr){
                minn[root] += val;
                lazy[root] += val;
                return;
            }
            pushdown(root);
            int mid = (l + r) >> 1;
            if (ll <= mid)
                update(lson, l, mid, ll, rr, val);
            if (rr > mid)
                update(rson, mid + 1, r, ll, rr, val);
            minn[root] = min(minn[lson], minn[rson]);
        }
    
        inline bool query(){
            return minn[1] != 0;
        }
    }Seg;
    
    int n, m;
    
    pair<pair<int,int>, int> s[N];
    
    int id[N];
    
    int main(void) {
        ios::sync_with_stdio(false); 
        cin.tie(0); cout.tie(0);
        cin >> n >> m;
        m <<= 1;
        for(int i = 1; i <= n; ++ i){
            cin >> s[i].first.first >> s[i].first.second >> s[i].second;
            s[i].first.first <<= 1;
            s[i].first.second <<= 1;
            id[i] = i;
        }
        sort(id + 1, id + 1 + n, [&](int x, int y){
                return s[x].second < s[y].second;
                });
        int cur = 1;
        int ans = 1e9 + 7;
        for(int i = 1; i <= n; ++ i){
            while(cur <= n && !Seg.query()){
                Seg.update(1, 2, m, s[id[cur]].first.first, s[id[cur]].first.second, 1);
                ++ cur;
            }
            if (Seg.query())
                ans = min(ans, s[id[cur - 1]].second - s[id[i]].second);
            Seg.update(1, 2, m, s[id[i]].first.first, s[id[i]].first.second, -1);
        }
        cout << ans << '
    ';
        return 0;
    }
    


  • 相关阅读:
    SLA合规率是什么? SLA合规率实践分析
    如何借助Site24x7提高Azure VM的灵活性和效率?
    如何避免LLMNR / NBT-NS欺骗攻击?
    ITSM整治混乱秩序 | 看知名研究所如何解决帮助台管理
    如何使用Applications Manager轻松监控Nginx?
    vue中让input框自动聚焦
    pc端手机号填写与验证信息的样式
    vuex里面的this.$store.dispatch 和 this.$store.commit用法以及区别
    Vue 的状态管理工具 Vuex(Vuex的安装与使用)
    详解Vue的钩子函数(路由导航守卫、keep-alive、生命周期钩子)
  • 原文地址:https://www.cnblogs.com/Lanly/p/15241756.html
Copyright © 2011-2022 走看看