[题解]P2107 小 Z 的 AK 计划

P2107 小 Z 的 AK 计划

考虑反悔贪心。我们尽可能 AK 所有路过的机房,如果 AK 当前机房后时间不够用,则从所有 AK 过的机房(包括当前)中取耗时最长的删掉,直到时间够用或者没有机房为止。

可以用一个堆来维护耗时最长的机房。总时间 \(O(n\log n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
struct Nd{int x,t;}a[N];
priority_queue<int> q;
int n,m,t,ans,cur;
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].t;
	sort(a+1,a+1+n,[](Nd a,Nd b){return a.x<b.x;});
	for(int i=1;i<=n;i++){
		t+=a[i].x-a[i-1].x+a[i].t;
		q.push(a[i].t);
		cur++;
		while(!q.empty()&&t>m){
			cur--;
			t-=q.top();
			q.pop();
		}
		if(t>m) break;
		ans=max(ans,cur);
	}
	cout<<ans<<"\n";
	return 0;
}

另一种做法是线段树上二分。AK 机房的时间和走路的时间是两个因素,我们钦定其中一个就很简单了。

我们可以枚举每个 \(x_i\),问题转化为“仅走到 \(x_i\) 最多能 AK 多少机房”,也即“\(m-x_i\) 的时间内能 AK 多少个 \(1\sim i\) 的机房”。

为此我们可以按 \(x\) 为机房排序,枚举到 \(x_i\) 时,将 \(t_1,t_2,\dots t_x\) 扔到线段树的对应位置,线段树上二分即可。

总时间 \(O(n\log n)\)

posted @ 2025-11-25 10:52  Sinktank  阅读(118)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.