【堆+模拟】[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();
}
posted @ 2016-05-21 12:40  outer_form  阅读(253)  评论(0编辑  收藏  举报