如果每过一秒所有蚯蚓都等量变长,我们就不必真的修改每一条——记一个“公共偏移量”,让所有比较在相对值上进行。
题目
菜地里有
- 每条还活着的蚯蚓长度增加
毫米; - 取出当前最长的一条,切成两段:一段长
毫米,另一段长 毫米( 为切断时刻的长度),两段留在菜地中继续生长。
请输出前
输入格式
- 第一行六个整数
; - 第二行
个整数,表示初始时各蚯蚓的长度(不超过 )。
输出格式
- 第一行
个整数:第 到第 秒被切断蚯蚓的长度; - 第二行
个整数:第 秒结束后所有蚯蚓的长度,升序输出。
样例
样例输入
input
3 2 1 1 2 3
3 3 2样例输出
output
4 5
2 3 3 4 4 4样例解释
- 初始长度为
; - 第
秒:都长 毫米变为 ,切一条最长的 ,切成 与 ,记下 ,其余为 ; - 第
秒:变为 ,切最长的 ,切成 与 ,记下 ,其余为 ; - 第
秒:变为 ,切一条最长的 ( ,不再输出),切成 与 ; - 最终菜地里有
条: ,升序为2 3 3 4 4 4。
提示
三个来源的蚯蚓(初始的、左段的、右段的)各自长度单调不增,各用一个队列维护队首即可 O(1) 取最大值;全局加一个偏移量代替逐条加 q。
题解
点击查看题解
核心思路
直接每次排序/堆取最大是
- 初始蚯蚓降序放入队列
;每秒切出的左段进 、右段进 ; - 由于每轮的切割值单调不增,
也是单调队列——三个队首的最大值就是当前最长蚯蚓; - 用偏移量
off记录累计生长:队列中存“相对长度”,比较与输出时加上off; - 每秒开始先
off += q(把本秒生长量计入偏移),再取最长者切断。设其真实长度为 ,则 、 为两段此刻的实际长度,以A - off、B - off入队——它们与其他蚯蚓共用同一偏移,从下一秒起自然同步生长。
长度相等时任取其一,切断值相同,不影响输出。
复杂度分析
- 时间复杂度:
- 空间复杂度:
点击查看参考代码
cpp
#include <algorithm>
#include <climits>
#include <deque>
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n, m, q, u, v, t;
cin >> n >> m >> q >> u >> v >> t;
vector<long long> a(n);
for (auto& x : a) cin >> x;
sort(a.begin(), a.end(), greater<long long>()); // Q0:初始蚯蚓,降序
deque<long long> q1, q2; // 切出的左段、右段(单调队列)
long long off = 0; // 全局生长偏移
size_t p = 0;
vector<long long> cut;
for (long long s = 1; s <= t; ++s) {
off += q; // 本秒生长量先计入偏移
// 三队列队首取最大(相对值比较)
long long best = LLONG_MIN;
int which = 0;
if (p < a.size() && a[p] > best) { best = a[p]; which = 0; }
if (!q1.empty() && q1.front() > best) { best = q1.front(); which = 1; }
if (!q2.empty() && q2.front() > best) { best = q2.front(); which = 2; }
if (which == 0) ++p;
else if (which == 1) q1.pop_front();
else q2.pop_front();
long long x = best + off; // 切断时刻的实际长度
if (s <= m) cut.push_back(x);
long long left = x * u / v;
long long right = x - left;
q1.push_back(left - off); // 以当前偏移为基准入队
q2.push_back(right - off);
}
for (int i = 0; i < (int)cut.size(); ++i) {
if (i) cout << ' ';
cout << cut[i];
}
cout << '\n';
// 收集第 t 秒后的实际长度并升序输出
vector<long long> rest;
for (; p < a.size(); ++p) rest.push_back(a[p] + off);
for (auto x : q1) rest.push_back(x + off);
for (auto x : q2) rest.push_back(x + off);
sort(rest.begin(), rest.end());
for (int i = 0; i < (int)rest.size(); ++i) {
if (i) cout << ' ';
cout << rest[i];
}
cout << '\n';
return 0;
}本地运行与提交
powershell
pnpm lab:run -- labs/chapter-05/exercise/E-05-14-earthworms