【堆+模拟】[CodeForces-235E]printer
题目大意
我们考虑一个有这样功能的网络打印机: 他从时刻 0 开始工作, 每一秒钟他打印一
页纸。 某些时刻他会收到一些打印任务。 我们知道打印机会收到 n 个任务, 我们将它们
分别编号为连续的整数 1~n, 并且第 i 个任务用三个参数描述: t_i 表示接到的时间, s_i
表示任务要求你打印多少张, 以及 p_i 表示任务的一个优先级。 所有任务的优先级互不
相同。
当一个打印机收到一个任务时, 任务会进入一个队列并留下直到完成了这个任务为
止。 在任务队列非空时, 每个时刻, 打印机会选择队列里优先级最高的一个任务, 打印
一页。 你可以想象任务进入队列是瞬间的事情, 所以他可以在收到某个任务的时刻去执
行这个任务。
你会得到除了某个任务以外所有任务的信息: 你不知道某个任务的优先级是多少。
然而, 我们还额外的知道这个任务他完成时的时刻。 我们给你这些信息, 请求出这个未
知的优先级并对每个任务输出它完成时的时刻。
分析
由于打印机每个时刻是打印优先级最高的那一个任务,所以可以很容易地想到用一个堆来维护。
模拟打印过程
将任务根据时间排序,然后时间轴递增.
当前时间点为
找优先级
当可以加入任务x的时候,将堆中的所有任务取出来,并且找到将会在
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define MAXN 50000
using namespace std;
typedef pair<int,int>pii;
typedef pair<int,pii>pip;
priority_queue<pip>q;
pip tmp[MAXN+10];
template<class T>
void Read(T &x){
char c;
bool f=0;
while(c=getchar(),c!=EOF){
if(c=='-')
f=1;
if(c>='0'&&c<='9'){
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';
ungetc(c,stdin);
if(f)
x=-x;
return;
}
}
}
int n,cnt,x,pset[MAXN+10];
long long T,ans[MAXN+10];
struct task{
int t,s,p,pos;
inline task(){
}
inline task(int t,int s,int p,int pos):t(t),s(s),p(p),pos(pos){
}
bool operator<(const task&a)const{
return t<a.t;
}
}a[MAXN+10];
void read(){
Read(n);
int i,t,s,p;
for(i=1;i<=n;i++){
Read(t),Read(s),Read(p);
a[i]=task(t,s,p,i);
pset[i]=p;
}
Read(T);
}
long long check(int p){
int i;
long long ret=0;
for(i=1;i<=cnt;i++)
if(tmp[i].first>=p)
ret+=tmp[i].second.second;
for(i=x+1;a[i].t<T&&i<=n;i++)
if(a[i].p>=p)
ret+=a[i].s;
return ret;
}
int Divide_Conqure(int l,int r,int t){
int mid;
while(l<r){
mid=(l+r)>>1;
if(check(mid)<=T-t-a[x].s)
r=mid;
else
l=mid+1;
}
return l;
}
void solve(){
sort(a+1,a+n+1);
sort(pset+1,pset+n+1);
int i;
long long t;
pip u;
i=1,t=0;
while(!q.empty()||i<=n){
if(q.empty()||t==a[i].t){
t=a[i].t;
if(a[i].p==-1)
break;
q.push(pip(a[i].p,pii(a[i].pos,a[i].s)));
i++;
}
else{
if(i>n||t+q.top().second.second<=a[i].t){
u=q.top(),q.pop();
t+=u.second.second;
ans[u.second.first]=t;
}
else{
u=q.top(),q.pop();
u.second.second-=a[i].t-t;
q.push(u);
t=a[i].t;
}
}
}
x=i;
while(!q.empty()){
tmp[++cnt]=q.top();
q.pop();
}
a[i].p=Divide_Conqure(1,1000000000,t);
int tt=lower_bound(pset+1,pset+n+1,a[i].p)-pset;
while(a[i].p==pset[tt]&&tt<=n)
a[i].p++,tt++;
for(i=1;i<=cnt;i++)
q.push(tmp[i]);
i=x;
printf("%d\n",a[x].p);
while(!q.empty()||i<=n){
if(q.empty()||t==a[i].t){
t=a[i].t;
q.push(pip(a[i].p,pii(a[i].pos,a[i].s)));
i++;
}
else{
if(i>n||t+q.top().second.second<=a[i].t){
u=q.top(),q.pop();
t+=u.second.second;
ans[u.second.first]=t;
}
else{
u=q.top(),q.pop();
u.second.second-=a[i].t-t;
q.push(u);
t=a[i].t;
}
}
}
}
void print(){
int i;
for(i=1;i<n;i++)
printf("%I64d ",ans[i]);
printf("%I64d\n",ans[n]);
}
int main()
{
read();
solve();
print();
}