1 条题解
-
0
自动搬运
来自洛谷,原作者为

一扶苏一
休息结束。邮箱 yifusuyi@qq.com搬运于
2025-08-24 23:16:40,当前版本为作者最后更新于2025-05-24 18:55:45,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
可以发现所有音符的时长都是 分音的倍数,因此可以一个 分音的时长作为单位长度构建一个时间轴。只有在轴的刻度上的时刻需要判断。然后依照题意解析输入的字符串,在音符对应的时间区间上标记当前区间内按下按键编号。最后扫描一遍时间轴,检查每个时间点上维护的按键有没有重复或超过三个即可。
更具体的,对每一个时刻维护一个 vector 存放该时刻被按下的按键编号。对于某一个时刻的 tap,直接把该 tap 扔到相应时刻的 vector 里。对于一个 个 分音的 hold,其长度是 个 分音。如果当前时刻是 ,其对应的按压区间是 。在这个区间内的时刻的 vector 里都加入相应的按键编号即可。注意 hold 按压时间是闭区间,首尾时刻的 vector 都要加入。
#include <bits/stdc++.h> const int maxn = 100'000; const int base = 96; int T; std::vector<int> timeLine[maxn]; int main() { std::cin >> T; for (auto _ : std::views::iota(0, T)) { int n; std::cin >> n; for (auto &i : timeLine) i.clear(); int curT = 0; for (auto _ : std::views::iota(0, n)) { std::string line; std::cin >> line; auto split = [](const std::string &s, char ch) -> std::vector<std::string> { std::vector<std::string> ret; std::string cur; for (auto i : s) { if (i == ch) { ret.push_back(cur); cur.clear(); } else { cur += i; } } if (!cur.empty()) ret.push_back(cur); return ret; }; auto splited = split(line, ','); int notevalue = std::stoi(splited[0].substr(1)); int noteTime = base / notevalue; splited.erase(splited.begin()); for (auto notes : splited) { auto note = split(notes, '/'); for (auto i : note) { auto button = std::stoi(i); if (i.size() == 1) { timeLine[curT].push_back(button); } else { auto body = i.substr(3, int(i.size() - 2)); auto splitedHold = split(body, ':'); int x = std::stoi(splitedHold[0]), y = std::stoi(splitedHold[1]); int holdTime = y * (base / x); for (int t = 0; t <= holdTime; ++t) { timeLine[curT + t].push_back(button); } } } curT += noteTime; } } bool ans = true; for (auto &i : timeLine) if (i.size() > 2) { ans = false; break; } else if (i.size() == 2 && i[0] == i[1]) { ans = false; } std::cout << (ans ? "Yes" : "No") << std::endl; } }验题人
/user/88479行的 R:https://www.luogu.com.cn/paste/gr6xtbky
- 1
信息
- ID
- 12306
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- (无)
- 递交数
- 0
- 已通过
- 0
- 上传者