“才开始40分钟?”
“我都AK了”
“可我的气球呢?”
——赤耳淡定又忧伤地说道
由于选手们实力过强,不断传来题目被AC的信息,发气球的志愿者小姐姐们实在忙不过来了。
初始所有志愿者小姐姐均在等待区,每当有一道题目被AC,等待区就会产生一个气球。
志愿者小姐姐发气球遵循以下规则:
1.如果此时等待区有志愿者,则志愿者出发将此气球发给对应的队伍,并在t时间后返回等待区。
2.如果此时等待区没有志愿者,则等待某一个志愿者回到等待区再出发发这只气球。
3.当一个志愿者回到等待区时,等待区有待发放的气球,则这个志愿者会优先发放最早产生的气球。
(如果有同时产生的气球,则优先发放对应队伍编号小的。)
队员们在自己AC题目之后都翘首以待,盼着志愿者小姐姐出发向自己走来,而后在座位边亲手插上一只气球。
俗话说的好,一时不见,思之如狂,便因而生恨。
当某一队伍在a时刻AC了某道题后,而小姐姐在b时刻才出发发对应的气球,则这个队伍的怒气值会增加b-a。
如果某个队伍在任意时刻时怒气值大于或等于d,则会愤怒离场。
鸡尾酒只希望有队伍AK离场,不希望有队伍愤怒离场.现在给你一场比赛的题目AC信息,请你帮鸡尾酒算算,他最少需要几个志愿者小姐姐来帮助他发气球才能保证没有队伍会愤怒离场且所有气球都被发放。
输入描述
第一行输入四个整数n,m,t,d,分别代表题目AC信息的数量,队伍数量,志愿者发一个气球所需要的时间,怒气值上限(n,m≤2*〖10〗5,t,d≤〖10〗9)。
接下来n行,每行包含两个整数a_i,b_i,描述一个题目AC的信息,a_i 代表队伍AC某道题的时间,b_i 代表这个队伍的编号.(a_i≤10^9,b_i≤m)
输出描述
输出一行一个整数代表最少需要的小姐姐数量。
样例输入 1
3 2 2 3
1 1
3 1
2 2
样例输出 1
1
题意:
四个整数n,m,t,d,分别代表题目AC信息的数量,队伍数量,志愿者发一个气球所需要的时间。
若比赛现场的等待区中有自愿者小姐姐,小姐姐会去发放气球,往返时间t。
若此时等待区没有小姐姐,则需要等到小姐姐返回等待区,再去发放气球,这个小姐姐会优先发放最早产生的气球。(如果有同时产生的气球,则优先发放对应队伍编号小的。)
当某一队伍在a时刻AC了某道题后,而小姐姐在b时刻才出发发对应的气球,则这个队伍的怒气值会增加b-a。如果某个队伍在任意时刻时怒气值大于或等于d,则会愤怒离场。
思路:
二分小姐姐数量,将每个小姐姐放置到有限队列里(由于AC信息不同,小姐姐返回的时间也不同,所有提前返回的小姐姐去发放气球)
若等待区有小姐姐,那么确定小姐姐的返回时间,放到队列中;若等待区里没有小姐姐,则需要等到小姐姐返回到等待区,当此时该队伍的怒气值会增加b-a,当怒气值累加达到d时,该队伍就会离开。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,t,d;
struct NODE
{
int a,b;
}node[210000];
int cnt[210000];
bool cmp(NODE x,NODE y)
{
if(x.a == y.a) return x.b < y.b;
return x.a < y.a;
}
bool solve(int x)
{
priority_queue <int,vector<int>,greater<int> > q;
for(int i=1;i<=x;i++){
q.push(0);
}
for(int i=1;i<=m;i++) cnt[i]=d;
for(int i=1;i<=n;i++){
int tem=q.top();q.pop();
if(tem>=node[i].a+cnt[node[i].b]) return false;
if(tem<=node[i].a) q.push(node[i].a+t);
else q.push(tem+t),cnt[node[i].b]-=tem-node[i].a;
}
return true;
}
int main()
{
cin>>n>>m>>t>>d;
for(int i=1;i<=n;i++){
cin>>node[i].a>>node[i].b;
}
sort(node+1,node+1+n,cmp);
int l=1,r=n;
while(r-l>1){
int Mid = (l+r)>>1;
if(solve(Mid)) r = Mid;
else l = Mid+1;
}
if(solve(l)) cout<<l<<endl;
else cout<<l+1<<endl;
return 0;
}