题目
大致题意
有n件包裹,每次可以取k件。给出每件包裹入库时间和最晚取走时间。(入库当天和最晚取走当天都可以取快递)问:最少几次可以将所有包裹取出。
思路
贪心。最小的
r
r
r一定要有一次把它取出来,所以每次在最小
r
r
r当天取出包裹即最优。
对
r
r
r从小到大排序,遍历,每次都对最小的
r
r
r进行处理。
如果当前
l
l
l小于等于确定去快递点的时间
r
r
r时,就和离
l
l
l最进时间点
r
r
r一起取走,此时确定去快递点的时间
r
r
r拿包裹的件数加一,若此时那确定去快递点的时间
r
r
r拿满了,说明不能之后的包裹无法在此时刻
r
r
r拿,即删除此
r
r
r;
如果当前
l
l
l大于所有已存的确定去快递点的时间
r
r
r就当前
r
r
r时间时拿一次(
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;
}