1 条题解
-
0
自动搬运
来自洛谷,原作者为

gcwixsxr
lxyddd搬运于
2025-08-24 22:15:32,当前版本为作者最后更新于2020-09-11 09:10:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这是一道比较经典的反悔贪心。
原来CTSC还有这样的水题。什么是反悔贪心呢?用通俗的话讲,由于贪心只注重当前的最优解,有时候无法得到全局最优解。反悔贪心就是在发现比当前最优解还要优时进行反悔操作。
看到这道题,题意大致可以理解为:给你 个区间,规定区间的的长度为 ,左端点不能超过 ,要使得区间个数最多,并且使得区间长度之和最小。
这里我们不妨定义一个数组 ,表示第 个区间的右端点不超过 , 在数值上等于 ,那么贪心策略又是什么?
我们不妨设 ,此时我们已经选出了满足要求的若干个区间,记这些区间的长度总和为 ,区间长度的最大值为 ,现在循环到了第 个区间,如果发现 ,那么代表当前区间可以被选择,则区间个数加一,区间长度加 ,否则,如果,那么代表当前区间就没有用了吗?不对,因为题目还有一个条件——要使区间长度之和最小。为了使每一个区间都物尽其用,我们还可以将 和 相比较,如果 ,则可以将长度为 的区间从原来满足要求的区间们中取出,重新插入当前的区间,还要记得更新区间的总长度。那如果 呢?那这个区间是真的没用了。
说了一堆,反悔在哪呢,就是在取出长度为 的区间,插入当前的区间中。一般贪心是没有这个操作的。为了取得全局最优值,只能舍弃掉一些相对更劣质的决策,加入更优质的决策。
最大值可以用堆来维护。
贴上代码:
#include<bits/stdc++.h> using namespace std; const int MAXN=2e5+2; #define int long long struct interval{ int len,r; bool operator <(const interval & x)const{ return r<x.r; } }a[MAXN]; int f[MAXN]; int n,num,sum; priority_queue<int>qu; signed main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i].r>>a[i].len; a[i].r+=a[i].len; } sort(a+1,a+n+1); for(int i=1;i<=n;i++){ if(sum+a[i].len<=a[i].r){ num++; sum+=a[i].len; qu.push(a[i].len); } else if(qu.top()>a[i].len){ sum-=qu.top(); qu.pop(); qu.push(a[i].len); sum+=a[i].len; } } cout<<num<<endl<<sum<<endl; return 0; }
- 1
信息
- ID
- 4916
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者