每日一题 [JSOI2007]建筑抢修

[JSOI2007]建筑抢修

https://ac.nowcoder.com/acm/problem/20154

这题的思路和https://ac.nowcoder.com/acm/problem/50439 类似
在我们看来,每一段都存在一个截至区域,首先肯定是要把截至区域按从小到大的顺序排列,这样之前的选择会为后面的选择腾出更多的时间,这个贪心就是可行的。
既然所选需要最多,有些我选择过后,如果当前总和小于截至日期,直接选择,但是后期选择的时候你会发现个问题,如果你选择当前的,结果后期的修理时间比他小的值可能无法在截至日期前完成,那么就会缩小选择区域,那么我们可以用后者替换当前已选择的最大修理时间那个,因为截止时间从小到大排列,把修理时间多的改为少的,可行性会更优。
所以我们只需要弄个优先队列,每次找出已选择的最大修理时间,如果当前修理时间小于它,则可以替换

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int maxn=2e5+7;
priority_queue<int> pa;

struct node {
  int v,s;
}a[maxn];

bool cmp(node a,node b)
{
  return a.s<b.s;
}

signed main()
{

  int n;
  cin>>n;
  for (int i=1;i<=n;++i)
  {
    cin>>a[i].v>>a[i].s;
  }
  sort(a+1,a+n+1,cmp);///反排序
  int cnt=1,ans=a[1].v;
  pa.push(a[1].v);
  for (int i=2;i<=n;++i)
  {
    if ((ans+a[i].v)<=a[i].s)///当前可选直接选
    {
      pa.push(a[i].v);
      ++cnt;
      ans+=a[i].v;
    }
     else if (a[i].v<pa.top())///如果不可选,则看是否可以使得解更优
      {
        ans-=pa.top();
        pa.pop();
        pa.push(a[i].v);
        ans+=a[i].v;
      }
  }
  cout<<cnt<<endl;
  return 0;
}
全部评论

相关推荐

2024-11-19 15:16
武汉理工大学 Java
喀什克尔的胡杨:秋招面了很多主管,感觉主管都是傻蛋
点赞 评论 收藏
分享
2024-12-04 19:53
已编辑
湖南文理学院 产品经理
牛客224543458号:他想找牛马,愿意疯狂加班的,因为要证明自己
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务