Codeforces #594 div1 C/div2 E – Queue in the Train

题目链接:https://codeforces.com/contest/1239/problem/C

题意:火车上有n位乘客,按照1到n编号,编号为i的人会在ti分钟想去打水。水箱只能供一位乘客使用,每位乘客会使用p分钟。当一位乘客想要去打水时,他会先看编号在他前面的乘客是不是都在座位上,如果有人没在座位上,他会坐下继续等待,否则他会去排队打水。当某一时刻有几位乘客同时想要打水时,编号最小的乘客会前去打水,其他人会坐下继续等待,计算每位乘客打完水的时间。

做法:模拟。按照题意模拟即可,具体实现见代码。首先我们需要一个优先队列判断座位上的人谁先去打水,然后我们需要一个优先队列判断坐在座位上等待的人,接着我们需要一个队列模拟正在排队的人,最后我们需要一个数据结构记录空的座位。按照题意模拟即可,具体实现见代码。

参考代码:

#include <iostream>
#include <queue>
#include <set>

using namespace std;
struct passenger
{
    int pos, startime;
} psger[100005];

struct cmp_waiting
{
    bool operator()(const passenger &x, const passenger &y)
    {
        return x.pos > y.pos;
    }
};

struct cmp_sitting
{
    bool operator()(const passenger &x, const passenger &y)
    {
        if (x.startime == y.startime)
            return x.pos > y.pos;
        else
            return x.startime > y.startime;
    }
};

priority_queue<passenger, vector<passenger>, cmp_sitting> sitting;
priority_queue<passenger, vector<passenger>, cmp_waiting> waiting;
queue<passenger> queuing;
set<int> emptyseat;
long long ret[100005];

int main()
{
    int n;
    long long p, now;
    cin >> n >> p;
    for (int i = 1; i <= n; ++i)
    {
        cin >> psger[i].startime;
        psger[i].pos = i;
        sitting.push(psger[i]);
    }
    now = sitting.top().startime;
    emptyseat.insert(n + 1);
    while (!sitting.empty() || !queuing.empty() || !waiting.empty())
    {
        if (!queuing.empty())
        {
            passenger fir = queuing.front();
            queuing.pop();
            now += p;
            ret[fir.pos] = now;
            while (!sitting.empty() && sitting.top().startime <= now)
            {
                passenger sec = sitting.top();
                if (sec.pos < *emptyseat.begin())
                {
                    emptyseat.insert(sec.pos);
                    queuing.push(sec);
                }
                else
                    waiting.push(sec);
                sitting.pop();
            }
            emptyseat.erase(fir.pos);
        }
        if (queuing.empty() && waiting.empty())
            now = max(now, (long long) sitting.top().startime);
        while (!sitting.empty() && sitting.top().startime <= now)
        {
            waiting.push(sitting.top());
            sitting.pop();
        }
        int id = *emptyseat.begin();
        if (!waiting.empty() && waiting.top().pos < id)
        {
            queuing.push(waiting.top());
            emptyseat.insert(waiting.top().pos);
            waiting.pop();
        }
    }
    for (int i = 1; i <= n; ++i)
        cout << ret[i] << " ";
    return 0;
}

原文地址:https://www.cnblogs.com/mapleaves/p/11808907.html

时间: 2024-11-06 07:20:25

Codeforces #594 div1 C/div2 E – Queue in the Train的相关文章

水题 Codeforces Round #303 (Div. 2) D. Queue

题目传送门 1 /* 2 比C还水... 3 */ 4 #include <cstdio> 5 #include <algorithm> 6 #include <cstring> 7 #include <cmath> 8 #include <iostream> 9 using namespace std; 10 11 typedef long long ll; 12 13 const int MAXN = 1e5 + 10; 14 const i

Codeforces Round #FF(255) DIV2 C - DZY Loves Sequences

A - DZY Loves Hash 水题,开辟一个数组即可 #include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; int main(){ int p,n; cin >> p >> n; vector<bool> buckets(302,false); bool flag = fal

Codeforces gym Hello 2015 Div2 B

Codeforces gym 100571 problem B Problem 设函数F(x),F(1)与F(2)已知,且当 i>=3,F(i)=a*F(i-2)+b*F(i-1).再给一个长度为N的数列A,进行Q次如下操作:每次给一个区间[L, R],对于每个k(L=<k<=R),将A[k]=A[k]+F[k-L+1].最后输出数列A(mod 10^9+7). Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N, Q: [1, 10^

Codeforces #504(div1+div2) 1023D Array Restoration(线段树)

题目大意:给你一个数组,数组是经过q次区间覆盖后的结果,第i次覆盖是把区间内的值赋值为i,其中有若干个地方数值未知(就是0),让你判断这个数组是否可以经过覆盖后得到的,如果可以,输出任意一种可行数组. 思路:不合法的情况只有2种.1:两个相同的数字中间出现了比它小的数字,比如: 6 5 6 就不合法,因为覆盖6的时候是覆盖连续的一段区间,而5比6先覆盖,所以这种情况不存在.我赛后看AC代码的时候发现有的人只是判断是否出现谷形的情况,这种是不对的. 比如这种样例:3 3 3 1 2 这种判断方法会

Codeforces #505(div1+div2) B Weakened Common Divisor

题意:给你若干个数对,每个数对中可以选择一个个元素,问是否存在一种选择,使得这些数的GCD大于1? 思路:可以把每个数对的元素乘起来,然后求gcd,这样可以直接把所有元素中可能的GCD求出来,从小到大枚举即可,需要特判一下第一个元素是素数的情况. #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<map> #include<s

Codeforces #505(div1+div2) D Recovering BST

题意:给你一个升序的数组,元素之间如果gcd不为1可以建边,让你判断是否可以建成一颗二叉搜索树. 解法:dp,首先建图,然后进行状态转移.因为如果点k左端与i相连,右端与k相连,则i和k可以相连,同时像左右两端拓展. 最后判断1和n是否相连即可. #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> using namespa

codeforces #305 div1 done

总算搞定了这一场比赛的题目,感觉收获蛮大 其中A,B,C都能通过自己的思考解决掉 D题思路好神,E题仔细想想也能想出来 以后坚持每两天或者一天做一场CF的div1的全套题目 除非有实在无法做出来的题目,每道题目还是都要写题解的 (我这算不算立flag? 本蒟蒻写的题解的链接: A:http://www.cnblogs.com/joyouth/p/5352953.html B:http://www.cnblogs.com/joyouth/p/5352932.html C:http://www.cn

Codeforces Round #326(Div2)

CodeForces 588A 题意:Duff喜欢吃肉,想在接下来的n天,每天都有Ai斤肉吃,但每一天肉的单价Pi不定,肉 可以保存不过期,现已知n天每天肉的斤数Ai,以及单价Pi,为了使每天都             有想要的Ai斤肉吃,求最小花费.  思路:cost=Ai*min(pi)  1<=i<=n; 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using

codeforces #334 div1 603C Lieges of Legendre(博弈)

题目链接: codeforces 603C 题目大意: 有两个人做游戏,游戏规则如下: 有n堆石子,每次可以对一堆石子进行操作,如果当前石子是偶数,那么可以选择将这2*x个石子分成k堆石子数为x的石子堆,还有一种没有前提的操作是取走当前堆的一个石子,问先手赢还是后手赢,先手和后手都足够聪明的情况下. 题目分析: 首先对于这种组合游戏的题目,很容易想到利用SG函数来解.我们对于游戏的局势进行分类讨论: 当k是偶数的情况下, 我们可以知道如果要把一个偶数堆分成k个堆,相当于将局势转到一个新的组合游戏