我们月赛用这题弱化了数据改了到月赛题…我居然不会…
http://www.thesky341.top 可以进去看看,题目为接热水
这题其实相对于我以前写的模拟而言是比较容易的,那么为什么会卡勒,
1.对stl 不熟悉,居然忘记 set 找数是无敌的存在
2.对题目思路理不清,无法分清里面所包含的数据结构
不多说,
这题其实可以分为三种人,排队的人,未口渴的人,口渴坐着的人
分别就对应了一个队列,一个以编号小优先的优先队列,以及一个按谁先口渴谁先排好序的数组(口渴时间同则按编号小排)
此时共两中大情况
一种是有人在排队
有人在排队是先把这个人该处理的处理了,
然后在他接水时口渴的人一个个处理,口渴前面没人,加入排队,有人则加入醒来没去行列
一种是没有人在排队
那么肯定是让坐着口渴的人先去排
如果没有坐着的人在考虑现在口渴的人去排,注意这个时候可能会有一段时间没人排,所以记得更新 nowt (去排的时间)
具体代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MA = 1e5+5;
struct stu{
int w,pos;
bool operator < (const stu B) const{
return this->pos > B.pos;
} //优先队列 醒来人位置优先
}a[MA];//a[]为按醒来顺序一个个来!
priority_queue<stu> xinq; //醒来的在等的人
queue<stu> q; //排队 先进先出
set<int> s; //排队 有哪些人
ll ans[MA];
int comp(stu c, stu d)
{
return c.w == d.w ? c.pos < d.pos : c.w < d.w;
}
int main()
{
int n,P;
scanf("%d%d",&n,&P);
for (int i = 0; i < n; i++)
{
scanf("%d",&a[i].w);
a[i].pos = i;
}
sort(a,a+n,comp);
ll nowt = a[0].w;
int p = 0; // nowt表示现在第几分钟 p表示现在醒了第几个
s.insert(n); //至少留个数比较
while( p < n || !q.empty() || !xinq.empty() )
{
stu k;
if(!q.empty()) //有人排队
{
nowt += P;
k = q.front(); q.pop();
ans[k.pos] = nowt; //把排第一个的事搞定
while(p < n && a[p].w <= nowt)//醒来的人何去何从
{
int bian = *s.begin();//排队里面最小的编号
if( a[p].pos < bian)
{
s.insert(a[p].pos);
q.push(a[p++]);
}
else
{
xinq.push(a[p++]);
}
}
s.erase(k.pos);
}
else //没人排队
{
if(!xinq.empty()) //有人坐着
{
k = xinq.top();
xinq.pop();
}
else //没人坐着
{
nowt = max(nowt,(ll)a[p].w);
k = a[p++];
}
q.push(k);
s.insert(k.pos);
}
}
for (int i = 0; i < n; i++)
{
if(!i) printf("%I64d",ans[i]);
else printf(" %I64d",ans[i]);
}
}