题意
[
c
]
[c]
[c]表示对
c
c
c向下取整
第0秒,你有
n
n
n只蚯蚓,第
i
i
i只蚯蚓的长度为
a
i
a_{i}
ai(长度均为非负整数,可以为0)。
每过一秒找出最长的蚯蚓切成两条长度为
[
p
x
]
[px]
[px]和
x
−
[
p
x
]
x-[px]
x−[px]的蚯蚓,
p
p
p为0到1之间的有理数,同时其余的所有蚯蚓长度增加
q
q
q(非负整常数)。
问
m
m
m秒内每一秒被切断的蚯蚓被切断前的长度
和
m
m
m秒后所有蚯蚓的长度
思路
每秒都要找最长的蚯蚓切成两条,因为新增了蚯蚓,所以我们直接对数组进行这样的操作会浪费大量的时间在排序和插入上,这时候可以这么想:
一条长度为
x
x
x的蚯蚓,切了以后变成长度为
[
p
x
]
[px]
[px]和
x
−
[
p
x
]
x-[px]
x−[px]的蚯蚓,因为
p
p
p是常数,所以很明显,
[
p
x
]
[px]
[px]和
x
−
[
p
x
]
x-[px]
x−[px]中有一个较大的值和一个较小的值(当然也可能一样大),并且
[
p
x
]
[px]
[px]和
x
−
[
p
x
]
x-[px]
x−[px]关于
x
x
x单调递增
所以我们可以用队列来处理蚯蚓的长度:
第一个队列,从大到小记录原有的所有蚯蚓的长度
第二个队列,从大到小记录被切以后
[
p
x
]
[px]
[px]的长度
第三个队列,从大到小记录被切以后
x
−
[
p
x
]
x-[px]
x−[px]的长度
由于第一个队列的蚯蚓都是从大到小记录的,所以我们把蚯蚓切了以后放到第二、第三个队列的时候,他们自然也会变成从大到小记录,不需要再次排序。
蚯蚓每秒都会增加 q q q的长度,如果我们一个个对长度进行修改肯定是会超时的,所以我们可以让我们的队列都只记录第0秒时蚯蚓的长度,需要切的时候再把长度加上就可以了。当然,切出新的蚯蚓往队列里加的时候,长度要减去相应个 q q q,储存第0秒时蚯蚓的长度,当蚯蚓是一开始就存在的
接下来只要每秒从三个队列的头中找出最长的蚯蚓切掉就好了
看下面的代码注释可能会更清楚
代码
*因为之前提交的时候爆int了,就索性全部换成long long了,不知道具体是哪里爆了
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
long long n; //蚯蚓的数量
long long a[100005] = {0}; //蚯蚓的长度,下标从1开始
long long q; //每秒钟蚯蚓长度增加q
long long m; //m秒后救兵到来,程序结束
long long t; //输出参数
long long u, v; //切开蚯蚓的位置p=u/v
queue<long long> A[3]; //记录蚯蚓在第0秒的长度。下标0为原长,1为[px],2为x-[px]
cin >> n >> m >> q >> u >> v >> t;
//读入蚯蚓的长度
for (long long i = 1; i <= n; ++i) {
cin >> a[i];
}
//排序原蚯蚓长度并且读入队列A
//此后队列A降序排序
sort(a + 1, a + n + 1, greater<>());
for (long long i = 1; i <= n; ++i) {
A[0].push(a[i]);
}
//执行每秒要执行的操作
for (long long second = 1; second <= m; ++second) {
//找出三个队列中最长的蚯蚓切掉
long long maxQueue = 0; //记录最长的蚯蚓在哪个队列
long long maxLength = -2100000000;
for (long long i = 0; i < 3; ++i) {
//如果队列不为空则记录最长的蚯蚓的长度和所在的队列
if (!A[i].empty() && A[i].front() > maxLength) {
maxLength = A[i].front();
maxQueue = i;
}
}
A[maxQueue].pop(); //最长的蚯蚓切掉
//记录新增的两条蚯蚓的长度
maxLength += (second - 1) * q; //将长度还原到当前秒数
//输出第t、2t、3t秒被切掉的蚯蚓在切掉之前的长度
if (second % t == 0) {
cout << maxLength << " ";
}
//记录[px]和x-[px]在第0秒的长度
A[1].push(maxLength * u / v - second * q);
A[2].push(maxLength - maxLength * u / v - second * q);
}
cout << endl;
//输出m秒后从大到小第t、2t、3t个蚯蚓的长度
for (long long i = 1; i <= n + m; ++i) {
long long maxQueue = 0; //记录最长的蚯蚓在哪个队列
long long maxLength = -2100000000;
for (long long j = 0; j < 3; ++j) {
//如果队列不为空则记录最长的蚯蚓的长度和所在的队列
if (!A[j].empty() && A[j].front() > maxLength) {
maxLength = A[j].front();
maxQueue = j;
}
}
A[maxQueue].pop();
if (i % t == 0) {
cout << maxLength + m * q << " ";
}
}
return 0;
}