1. 程式人生 > >【堆+模擬】[CodeForces-235E]printer

【堆+模擬】[CodeForces-235E]printer

題目大意

我們考慮一個有這樣功能的網路印表機: 他從時刻 0 開始工作, 每一秒鐘他列印一
頁紙。 某些時刻他會收到一些列印任務。 我們知道印表機會收到 n 個任務, 我們將它們
分別編號為連續的整數 1~n, 並且第 i 個任務用三個引數描述: t_i 表示接到的時間, s_i
表示任務要求你列印多少張, 以及 p_i 表示任務的一個優先順序。 所有任務的優先順序互不
相同。
當一個印表機收到一個任務時, 任務會進入一個佇列並留下直到完成了這個任務為
止。 在任務佇列非空時, 每個時刻, 印表機會選擇佇列裡優先順序最高的一個任務, 列印
一頁。 你可以想象任務進入佇列是瞬間的事情, 所以他可以在收到某個任務的時刻去執
行這個任務。
你會得到除了某個任務以外所有任務的資訊: 你不知道某個任務的優先順序是多少。
然而, 我們還額外的知道這個任務他完成時的時刻。 我們給你這些資訊, 請求出這個未
知的優先順序並對每個任務輸出它完成時的時刻。

分析

由於印表機每個時刻是列印優先順序最高的那一個任務,所以可以很容易地想到用一個堆來維護。

模擬列印過程

將任務根據時間排序,然後時間軸遞增.
當前時間點為tn,當最近的一個可以加入任務時間點tx前堆頂可以完成任務的時候,就記錄這個任務完成的時間,將這個任務彈出棧頂,tn變為堆頂任務結束的時間。如果不能,就將堆頂任務的剩餘時間減去txtntn=tx

找優先順序

當可以加入任務x的時候,將堆中的所有任務取出來,並且找到將會在[tx,T)區間內加入的任務,二分任務x的優先順序px,令ret=pi>=pxsi,若ret>Ttxpx=mid+1,否則px=

mid,二分出的就是px的最小值,然後進行判重,在所有p值的集合中看是否出現px,沒有就可以,否則二分找到px的位置pos,然後將px,pos遞增,一旦不相等,px就可以作為答案了,然後繼續列印。

程式碼

#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(); }