[JSOI2007]建筑抢修

https://zybuluo.com/ysner/note/1218492

题面

\(n\)个建筑有维修时间\(T_1\)开始不可维修时间点\(T_2\),问最多能修多少建筑。

  • \(n\leq2*10^5\)

解析

显然先按\(T_2\)排序维修,同时维护\(-T_1\)小根堆。
能修就加上\(T_1\),否则如当前\(T_1\)小于堆顶就不修堆顶建筑转而修当前建筑。
能修就修,不能修就换。

然而我一开始弹堆顶的条件是弹完后可修当前建筑,缩小了弹的范围。。。
注意时刻向最优化。

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define re register
#define il inline
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=2e5+100;
ll n,tot;
struct dat
{
  ll t,g;
  bool operator < (const dat &o) const {return -t>-o.t;}
}a[N];
priority_queue<dat>Q;
il bool cmp(dat x,dat y){return x.g<y.g;}
il ll gi()
{
  re ll x=0,t=1;
  re char ch=getchar();
  while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  if(ch=='-') t=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  return x*t;
}
int main()
{
  n=gi();
  fp(i,1,n) a[i].t=gi(),a[i].g=gi();
  sort(a+1,a+1+n,cmp);
  fp(i,1,n)
    {
      if(tot+a[i].t<=a[i].g) Q.push(a[i]),tot+=a[i].t;
      else
    {
      re int gg=Q.top().t;
      if(gg>a[i].t) tot-=gg,Q.pop(),tot+=a[i].t,Q.push(a[i]);   
    }
    }
  printf("%lld\n",1ll*Q.size());
  return 0;
}
posted @ 2018-07-19 01:20  小蒟蒻ysn  阅读(136)  评论(0编辑  收藏  举报