题目
大致题意
有n件包裹,每次可以取k件。给出每件包裹入库时间和最晚取走时间。(入库当天和最晚取走当天都可以取快递)问:最少几次可以将所有包裹取出。
思路
贪心。最小的r rr一定要有一次把它取出来,所以每次在最小r rr当天取出包裹即最优。
对r rr从小到大排序,遍历,每次都对最小的r rr进行处理。
如果当前l ll小于等于确定去快递点的时间r rr时,就和离l ll最进时间点r rr一起取走,此时确定去快递点的时间r rr拿包裹的件数加一,若此时那确定去快递点的时间r rr拿满了,说明不能之后的包裹无法在此时刻r rr拿,即删除此r rr;
如果当前l ll大于所有已存的确定去快递点的时间r rr就当前r rr时间时拿一次(a n s + + ans++ans++),并且记录此时刻取包裹件数为1。
(大牛思路)
代码
#include<bits/stdc++.h>
using namespace std;
//#define ll long long
#define int long long
const int N = 1e5+10;
const double eps=1e-8;
struct node{//记录r最小
int l;int r;
bool operator <(const node &a)const{
if(r!=a.r) return r<a.r;
return l<a.l ;
}
}ar[N];
map<int,int>mp;
set<int>se;
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t,ans,n,k;cin>>t;
while(t--){
cin>>n>>k;
ans=0;mp.clear();se.clear();
for(int i=0,l,r;i<n;i++){
cin>>ar[i].l>>ar[i].r;
}
if(k==1){
cout<<n<<endl;continue;
}
sort(ar,ar+n);//r从小到大
for(int i=0;i<n;i++){//r从小到大 遍历
auto pos=se.lower_bound(ar[i].l );
//判断此包裹是否可以和前面某次一起取走
if(pos==se.end()){//无法一起取走
mp[ar[i].r ]=1;//此时刻拿一次包裹,包裹容量为1
se.insert(ar[i].r );
ans++;//取快递点次数加一
}else{//可以一起取走
int x=*pos;
if(++mp[x]==k)se.erase(x);//增加一件,若包裹容量满了则删除
}
}
cout<<ans<<endl;
}
return 0;
}
版权声明:本文为lalala625原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。