排序+模拟+优先队列——cf1248E

其实是个模拟题。。

/*
每个人都有一个口渴时间,如果口渴时,其前面没有人在排队,那么其就去排队接水,反之一直等到前面没有人排队
问每个人接完水的时间
每个没轮到的人都在位置上等前面的人接完水,然后他再去排队
先把每个人按照口渴时间排序
设新加入队列的人是now,那么口渴时间在 now.s->now.t 之间的所有人都会进入等待状态
    在now前面的人会直接去排队,在now后面的人会继续等待
当这条队列都排完后,那些等待状态中的,最靠前的人会去排队

依次类推,用队列维护排队的人,用优先队列维护等待的人
 
*/
#include<bits/stdc++.h>
#include<queue>
using namespace std;
#define N 100005
#define ll long long 
#define INF 0x3f3f3f3f3f3f3f3f

ll n,ans[N],P;
struct Node{
    ll s,id;
    bool operator<(Node b)const {
        return id>b.id;
    }
}p[N]; 
int cmp(Node a,Node b){
    if(a.s==b.s)return a.id<b.id;
    return a.s<b.s;
}
int main(){
    cin>>n>>P;
    for(int i=1;i<=n;i++){
        cin>>p[i].s;
        p[i].id=i;
    }
    sort(p+1,p+1+n,cmp);
    
    queue<Node>q;
    priority_queue<Node>pq;
    int index=1,finish=0;
    
    pq.push(p[1]); 
    ll time=p[1].s;
    while(1){
        Node cur;
        if(pq.size()){
            cur=pq.top();
            pq.pop();
        }
        else {
            cur=p[++index];
            time=p[index].s;//时间直接跳过去 
        }
        q.push(cur);
        
        while(index+1<=n){
            Node tmp=q.back();
            if(p[index+1].s<=time+1ll*q.size()*P){
                //放到pq里
                if(p[index+1].id>tmp.id)
                    pq.push(p[++index]);
                //放到q里
                else q.push(p[++index]); 
            }
            else break;
        }
        
        //q队列的的都可以出队了
        while(q.size()){
            Node tmp=q.front();q.pop();
            time+=P;
            ans[tmp.id]=time;
            finish++;
        }
        if(finish==n)break;
    }
    
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<' ';
}
原文地址:https://www.cnblogs.com/zsben991126/p/11739353.html