题解 P2107 【小Z的AK计划】

· · 题解

这题就一贪心

假设你有一种到了机房就必须AK的欲望

而且有超能力可以让自己AK的机房变得WA、TLE、MLE......,然后返还你的时间

假设你走到了一个机房,AK了之前的所有机房,但是时间超过了m,你是选择用时最少的机房WA掉,还是最多的呢(相当于路过)

答案肯定是不在用时最多的机房AK

于是按机房到家的距离从近到远排序

一个一个机房的去AK dreaming

当你当了i机房后,于是判断m时间是否用完,如果超了,那就反复使之前用最多时间AK的机房变得WA,并返还时间,直到用的时间少于m,那么继续往前走

在路上取max就好了

还没懂就看看代码实现

//12252024832524
#include <queue>
#include <cstdio>
#include <algorithm>
#define Max(x,y) (x>y?x:y)
using namespace std;

typedef long long LL;
const LL MAXN = 100005;
LL n,m;
struct node
{
    LL x,t;
    bool operator < (const node &px)const
    {
        return x < px.x;
    }
}cr[MAXN];//computer room 机房
priority_queue<LL> q;

LL Read()
{
    LL x = 0,f = 1;char c = getchar();
    while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    return x * f;
}

int main()
{
    n = Read();
    m = Read();
    for(int i = 1;i <= n;++ i)
    {
        cr[i].x = Read();
        cr[i].t = Read();
    }
    sort(cr+1,cr+n+1);//按距离排序 
    LL tim = 0,ans = 0,AK = 0;
    for(int i = 1;i <= n;++ i)
    {
        tim += cr[i].x - cr[i-1].x;//走到i机房所用时间 
        q.push(cr[i].t);//AK的欲望 
        AK++;
        tim += cr[i].t;
        while(!q.empty() && tim > m)//如果用的时间多于m,发动超能力 
        {
            AK --;
            tim -= q.top();
            q.pop();
        }
        if(tim > m)//返还所有时间,但是仍然超过了m 
            break;//别走了,再走也没时间AK了
        ans = Max(ans,AK);//取max 
    }
    printf("%lld",ans);
    return 0;
}