Package Delivery
贪心 优先队列
题意
- 有n个包裹,每个包裹有自己的到达日期和截止日期
- 某肥宅能一次拿k个包裹,一天内可取多次,没有限制
- 问如何安排能够使得取包裹的次数最少
思路
在ddl之前取包裹的收益一定不如ddl时,因为这时会有更多送达的包裹
也就是说,只有当有包裹ddl到了我们才会去取包裹,我们也不需要取完当时到达的所有包裹,就先取k个ddl最小的包裹,当然也不定有k个那就能取几个取几个
这个贪心策略挺好想的,可惜比赛时没想到用优先队列
代码
#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
const int mod=998244353;
struct Node{
int l,r;
};
struct cmp1{
bool operator () (const Node & a,const Node & b) const
{
return a.r>b.r;
}
};
bool cmp(Node x,Node y){
if(x.l==y.l) return x.r<y.r;
return x.l<y.l;
}
void solve(){
int n,k; cin>>n>>k;
vector<Node> a(n);
for(auto &i : a) cin>>i.l>>i.r;
sort(a.begin(),a.end(),cmp);//对包裹进行排序,按照到达日期升序
priority_queue<Node,vector<Node>,cmp1> que;
que.push(a[0]);
int ans = 0;
int day = a[0].r;
for(int i=1;i<n;){
while(i<n&&a[i].l<=day||day==-1){
if(day==-1) day = a[i].r;
day = min(day,a[i].r);
que.push(a[i]);
i++;
}
if(!que.empty()){
ans++;
if(que.size()<=k){
while(!que.empty()) que.pop();
day = -1;
}
else{
int tmp=k;
while(tmp--) que.pop();//取k个包裹,其他不用急着取,因为越晚取收益越大
day = que.top().r;
}
}
}
ans += (que.size()+k-1)/k; //最后不一定全部取完,对剩余的包裹向上取整求次数
cout<<ans<<le;
}
int main() {
fst;
int t; cin>>t;
while(t--){
solve();
}
return 0;
}