E. Boring Segments
2021/9/6 23:40:02
本文主要是介绍E. Boring Segments,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
E. Boring Segments
https://codeforces.com/contest/1555/problem/E
题目大意
给出\(n\)个区间的端点,和每个区间的价值,问你选择一些区间可以从 \(1\)走到\(m\)的最小花费。
只有区间有交集才可以互通,即:\([1,2]和[2,3]\)可以,但是\([1,2]和[3,4]\)是不能互通的。最小花费的定义是所选区间中的最大价值和最小价值之差。
解题思路
可以考虑尺取的思路。
因为这个题区间之间需要覆盖,但是覆盖问题不好处理,我们可以将 \(m\)和每个线段的右断点减\(1\),这样区间只要连续就满足条件了。
我们用线段树维护一个区间的最小值,每次选择一个区间就是将该线段的区间在线段树中加\(1\),然后查看\(1\)到\(m\)中的最小值是否是\(1\)即可判断所选区间是否覆盖\(1\)到\(m\),因为我们所选的区间在经过按权值排序后越连续越优(因为答案不受中间值影响,只与最左边和最右边值的影响),所以可以使用双指针每次让左端点尽可能右移,右端点相当于一个遍历的过程。
所以首先将线段按权值排序,然后从\(1\)到\(n\)扫一遍,当遍历到\(i\)时,首先将\(i\)这段区间在线段树中加\(1\),随后判断\(l\)是否可以右移,每次右移前更新答案即可,右移后将对应区间在线段树中减\(1\)。
Code
#include <bits/stdc++.h> #define ll long long #define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0) #define fi first #define se second #define PII pair<int, int> #define PLL pair<ll, ll> #define pb push_back #define V vector #define int ll using namespace std; const int N = 1e6 + 7; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const ll mod = 1e9 + 7; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x*f; } struct ${ int l,r,w; bool operator < ($ p)const{ if(w!=p.w)return w < p.w; else if(r != p.r)return r < p.r; else return l < p.l; } }a[N]; struct T{ int l,r,mid,mi,sum,lz; }tree[N << 2]; void pushup(int rt){ tree[rt].mi = min(tree[rt<<1].mi,tree[rt<<1|1].mi); } void pushdown(int rt){ if(tree[rt].lz != 0){ tree[rt<<1].lz += tree[rt].lz; tree[rt<<1].mi += tree[rt].lz; tree[rt<<1|1].lz += tree[rt].lz; tree[rt<<1|1].mi += tree[rt].lz; tree[rt].lz = 0; } } void build(int l,int r,int rt){ tree[rt].l = l; tree[rt].r = r; int mid = (l + r) >> 1; tree[rt].mid = mid; tree[rt].mi = tree[rt].lz = 0; if(l == r){ return; } build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void update(int l,int r,int v,int rt){ if(l <= tree[rt].l && tree[rt].r <= r){ tree[rt].lz += v; tree[rt].mi += v; return; } pushdown(rt); if(l <= tree[rt].mid) update(l,r,v,rt<<1); if(r > tree[rt].mid) update(l,r,v,rt<<1|1); pushup(rt); } int query(int l,int r,int rt){ if(l <= tree[rt].l && tree[rt].r <= r){ return tree[rt].mi; } pushdown(rt); int ret = 1e9; if(l <= tree[rt].mid) ret = min(ret, query(l,r,rt<<1)); if(r > tree[rt].mid) ret = min(ret, query(l,r,rt<<1|1)); return ret; } void solve(){ int n,m; cin >> n >> m; m--; int maxn = 0; for(int i = 1; i <= n; i++){ cin >> a[i].l >> a[i].r >> a[i].w; maxn = max(maxn,a[i].r); a[i].r --; } build(1,maxn,1); sort(a+1,a+1+n); int l = 1; int ans = 1e9; for(int i = 1; i <= n; i++) { update(a[i].l,a[i].r,1,1); while(l <= i && query(1,m,1)){ ans = min(ans,a[i].w - a[l].w); update(a[l].l,a[l].r,-1,1); l++; } } cout << ans << "\n"; } signed main() { #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif qc; int T = 1; //cin >> T; while(T--){ solve(); } return 0; }
这篇关于E. Boring Segments的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南