1 条题解

  • 0
    @ 2025-8-24 23:16:40

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 一扶苏一
    休息结束。邮箱 yifusuyi@qq.com

    搬运于2025-08-24 23:16:40,当前版本为作者最后更新于2025-05-24 18:55:45,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    可以发现所有音符的时长都是 9696 分音的倍数,因此可以一个 9696 分音的时长作为单位长度构建一个时间轴。只有在轴的刻度上的时刻需要判断。然后依照题意解析输入的字符串,在音符对应的时间区间上标记当前区间内按下按键编号。最后扫描一遍时间轴,检查每个时间点上维护的按键有没有重复或超过三个即可。

    更具体的,对每一个时刻维护一个 vector 存放该时刻被按下的按键编号。对于某一个时刻的 tap,直接把该 tap 扔到相应时刻的 vector 里。对于一个 yyxx 分音的 hold,其长度是 y×96/xy \times 96 / x9696 分音。如果当前时刻是 tt,其对应的按压区间是 [t,t+96y/x][t, t + 96y/x]。在这个区间内的时刻的 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
    400400 行的 R:https://www.luogu.com.cn/paste/gr6xtbky

    • 1

    信息

    ID
    12306
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    (无)
    递交数
    0
    已通过
    0
    上传者