Problem Description
Little Q likes online shopping very much. In the next 109 days, there will be n packages delivered to the post office in total. Let’s label the next 109 days as day 1, day 2, …, day 109 respectively. For the i-th package, it will arrive at the post office at day li, and the deadline to take it back home is day ri, which means Little Q can take it back home at day x if and only if li≤x≤ri.
Every time Little Q comes to the post office, he can take at most k packages together back home at the same time. Note that Little Q can go to the post office multiple times during a single day. Please help Little Q determine how to take these n packages back home such that the number of times he will go to the post office is minimized.
Input
The first line contains a single integer T (1≤T≤3000), the number of test cases. For each test case:
The first line contains two integers n and k (1≤k≤n≤100000), denoting the number of packages and the number of packages Little Q can carry at the same time.
Each of the following n lines contains two integers li and ri (1≤li≤ri≤109), describing a package.
It is guaranteed that the sum of all n is at most 1000000.
Output
For each test case, output a single line containing an integer, denoting the minimum possible number of times that Little Q will go to the post office.
Sample Input
1
4 2
1 3
2 4
6 7
4 7
Sample Output
2
思路:
枚举每个包裹的
r
i
r_i
ri,取走包含
r
i
r_i
ri且并未去走的k个的区间。
做法:
读入部分:
for(int i=0;i<n;i++)
{
arr[i].first=read();
arr[i].second=read();
ql[i]=i;
qr[i]=i;
del[i]=false;
}
要用scanf或者read,用cin的话会超时
ql数组用于对包裹的
l
l
l进行排序,qr数组用于对包裹的
r
r
r进行排序
arr数组用于记录每个包裹的信息,del记录这个包裹是否被取走(已被取走为true,未取走为false)。
排序部分:
sort(ql,ql+n,cmp1);
sort(qr,qr+n,cmp2);
分别将包裹标号按照包裹的
l
和
r
l和r
l和r进行排序
枚举
r
r
r部分
for(int i=0,j=0;i<n;i++)
{
if(del[qr[i]])
{
continue;
}
while(j<n && arr[ql[j]].first<=arr[qr[i]].second)
{
q.push({arr[ql[j]].second,ql[j]});
j++;
}
res++;
for(int u=0;u<k;u++)
{
if(q.empty())
{
break;
}
del[q.top().second]=1;
q.pop();
}
}
如果该包裹已被取走,那么continue
接着枚举每一个可以取走的包裹,即这个包裹的
l
l
l小于等于当前包裹的
r
r
r,并将他们入队。
res++代表这次取包裹,故计数+1
优先队列按照可取的包裹的
r
r
r进行排序,由于一次最多可取k个,故先去
r
r
r最小的前k个。(因为
r
r
r大的包裹可以以后再去,但是
r
r
r小的包裹这次不取下次就没了!)
将已取的包裹标记一下,弹出。
如果q是空的,就意味着这次取不到k个包裹,就不取了。(比方说最多可以去3个包裹,但是这次去的时候快递站只有一个包裹,当u=0的时候取走了这个包裹,u=1的时候就没包裹了,q就空了 )
完整代码:
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100005;
typedef pair<int,int>PII;
PII arr[N];
int ql[N],qr[N];
bool del[N];
priority_queue<PII,vector<PII>,greater<PII>>q;
inline bool cmp1(int x,int y)
{
PII a=arr[x];
PII b=arr[y];
if(a.first<b.first)
{
return true;
}
return false;
}
inline bool cmp2(int x,int y)
{
PII a=arr[x];
PII b=arr[y];
if(a.second<b.second)
{
return true;
}
return false;
}
inline int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++)
{
arr[i].first=read();
arr[i].second=read();
ql[i]=i;
qr[i]=i;
del[i]=false;
}
sort(ql,ql+n,cmp1);
sort(qr,qr+n,cmp2);
int res=0;
for(int i=0,j=0;i<n;i++)
{
if(del[qr[i]])
{
continue;
}
while(j<n && arr[ql[j]].first<=arr[qr[i]].second)
{
q.push({arr[ql[j]].second,ql[j]});
j++;
}
res++;
for(int u=0;u<k;u++)
{
if(q.empty())
{
break;
}
del[q.top().second]=1;
q.pop();
}
}
cout<<res<<endl;
}
}