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

来源:互联网 发布:激光剑多少钱淘宝网 编辑:程序博客网 时间:2024/06/06 11:45

题目大意

我们考虑一个有这样功能的网络打印机: 他从时刻 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 50000using 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();}
0 0