vp 2024冬季PAT甲级

前言

最后10分钟极限AK,第三题太BT了,用vector或者deque模拟都会TLE,只能上平衡树才能过。
此次做崩了,中途就把录屏停了,因此没有录屏

题目总览

15d7c030bd1ba54e4866222a4a613c6d
e115efd4853c9127f7a9db4d258296c4
ff544895a0b023a7b2cc65fc66ca3c8b

题目细览

第1题 A-1 Super A - B

image

思路

以字符串形式读入a和b,通过比较a是否小于b来判断答案是否为负数,然后先pop掉a和b最后的'0',然后通过给短的那个字符串末尾补'0'来对其两个字符串,然后根据答案是否为负数选择是否交换a和b以确保a > b,下标从2开始模拟,如果a[i] - b[i]够减就直接减,否则一直查询上一个数是否够减,然后将上一个数减一,输出前注意也要pop掉答案最后的'0',最后输出的时候先输出符号在输出数值。

我的AC代码

#include <bits/stdc++.h>

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  std::string sa, sb;
  std::cin >> sa >> sb;

  while (sa.back() == '0') {
    sa.pop_back();
  }
  while (sb.back() == '0') {
    sb.pop_back();
  }

  bool isNeg = (sa < sb);

  int lena = sa.size();
  int lenb = sb.size();

  if (lena < lenb) {
    for (int i = 0; i < lenb - lena; i++) {
      sa += '0';
    }
  } else if (lena > lenb) {
    for (int i = 0; i < lena - lenb; i++) {
      sb += '0';
    }
  }

  if (isNeg) {
    std::swap(sa, sb);
  }

  std::string ans = "0.";
  for (int i = 2; i < sa.size(); i++) {
    int d = sa[i] - sb[i];
    if (d < 0) {
      d += 10;
      for (int j = i - 1; j >= 2; j--) {
        if (ans[j] == '0') {
          ans[j] = '9';
        } else {
          ans[j]--;
          break;
        }
      }
      ans += char('0' + d);
    } else {
      ans += char('0' + d);
    }
  }

  while (ans.back() == '0') {
    ans.pop_back();
  }

  std::cout << (isNeg ? "-" : "") << ans << "\n";

  return 0;
}

第2题 A-2 Gala Night

image

思路

必须要要优化操作2的时间复杂度,如果使用了过多的map和set会TLE,参考我提交的九发TLE。思路就看代码吧,太细了说不上来。

我的AC代码

#include <bits/stdc++.h>

void solve() {
  int n;
  std::cin >> n;

  std::unordered_map<std::string, std::vector<int>> map;
  std::unordered_map<int, std::string> at;
  std::vector<int> all;
  all.reserve(n);
  std::unordered_map<int, bool> won;
  for (int i = 0; i < n; i++) {
    std::string id;
    int x;
    std::cin >> id >> x;

    map[id].push_back(x);
    at[x] = id;
    all.push_back(x);
  }

  std::sort(all.begin(), all.end());

  int q;
  std::cin >> q;

  for (int qi = 0; qi < q; qi++) {
    int op;
    std::cin >> op;

    if (op == 1) {
      int x;
      std::cin >> x;
      auto it = std::lower_bound(all.begin(), all.end(), x);
      if (it == all.end()) {
        std::cout << "ERROR\n";
      } else {
        std::cout << at[*it] << "\n";
        won[*it] = true;
      }
    } else if (op == 2) {
      std::string id;
      std::cin >> id;

      auto it = map.find(id);
      if (it == map.end()) {
        std::cout << "ERROR\n";
      } else {
        const auto& t = it->second;
        std::vector<int> ans;
        for (const auto& _ : t) {
          if (won[_]) {
            ans.push_back(_);
          }
        }
        if (ans.empty()) {
          std::cout << "\n";
        } else {
          for (int i = 0; i < ans.size(); i++) {
            std::cout << ans[i] << " \n"[i + 1 == ans.size()];
          }
        }
      }
    } else {
      int x;
      std::cin >> x;

      auto it = std::lower_bound(all.begin(), all.end(), x);
      if (it == all.end()) {
        std::cout << "ERROR\n";
      } else if (*it != x) {
        std::cout << "ERROR\n";
      } else {
        std::cout << at[*it] << "\n";
        won[*it] = true;
      }
    }
  }
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  int T = 1;
  // std::cin >> T;

  for (int Ti = 0; Ti < T; Ti++) {
    solve();
  }

  return 0;
}

第3题 A-3 Dancing Stacks

image

思路

实现一个数据结构,类似于栈,除了支持push和pop以外,还需要额外支持两个操作,一个是反转该数据结构内所有元素,另一个是两两交换数据结构内所有元素(从栈顶开始),如果操作到最后只剩下一个则跳过。我一开始打算用vector或者deque模拟,但是都TLE了,于是考虑用平衡树,我用了两个Treap来维护。

我的AC代码

#include <bits/stdc++.h>

using i64 = long long;

constexpr int inf1 = 1E9;
constexpr i64 inf2 = 1E18;
constexpr int P1 = 1E9 + 7, P2 = 998'244'353;

struct Node {
  int val, pri, sz, rev, l, r;
};

std::vector<Node> tr(200001);

int cnt = 0;

int new_node(int v) {
  ++cnt;
  tr[cnt].val = v;
  tr[cnt].pri = rand();
  tr[cnt].sz = 1;
  tr[cnt].rev = 0;
  tr[cnt].l = tr[cnt].r = 0;
  return cnt;
}

void push(int t) {
  if (t && tr[t].rev) {
    tr[t].rev = 0;
    std::swap(tr[t].l, tr[t].r);
    if (tr[t].l) {
      tr[tr[t].l].rev ^= 1;
    }
    if (tr[t].r) {
      tr[tr[t].r].rev ^= 1;
    }
  }
}

void update(int t) {
  if (t) {
    tr[t].sz = tr[tr[t].l].sz + tr[tr[t].r].sz + 1;
  }
}

void split(int t, int k, int& a, int& b) {
  if (!t) {
    a = b = 0;
    return;
  }
  push(t);
  int leftSize = tr[tr[t].l].sz;
  if (k <= leftSize) {
    split(tr[t].l, k, a, tr[t].l);
    b = t;
  } else {
    split(tr[t].r, k - leftSize - 1, tr[t].r, b);
    a = t;
  }
  update(t);
}

int merge(int a, int b) {
  if (!a) return b;
  if (!b) return a;
  push(a);
  push(b);
  if (tr[a].pri > tr[b].pri) {
    tr[a].r = merge(tr[a].r, b);
    update(a);
    return a;
  } else {
    tr[b].l = merge(a, tr[b].l);
    update(b);
    return b;
  }
}

int pop_front(int& root) {
  push(root);
  int left, right;
  split(root, 1, left, right);
  int val = tr[left].val;
  root = right;
  return val;
}

int pop_back(int& root) {
  push(root);
  int sz = tr[root].sz;
  int left, right;
  split(root, sz - 1, left, right);
  root = left;
  return right;
}

void solve() {
  int q;
  std::cin >> q;

  int E = 0, O = 0;
  int n = 0;

  for (int qi = 0; qi < q; qi++) {
    int op;
    std::cin >> op;
    if (op == 0) {
      int x;
      std::cin >> x;

      int newnode = new_node(x);
      int newE = merge(newnode, O);
      O = E;
      E = newE;
      n++;
    } else if (op == 1) {
      if (n == 0) {
        std::cout << "-1\n";
      } else {
        int val = pop_front(E);
        std::cout << val << "\n";
        int oldO = O;
        O = E;
        E = oldO;
        n--;
      }
    } else if (op == 2) {
      if (n == 0) continue;
      if (E) tr[E].rev ^= 1;
      if (O) tr[O].rev ^= 1;
      if (n % 2 == 0) {
        std::swap(E, O);
      }
    } else {
      if (n == 0) continue;
      if (n % 2 == 0) {
        std::swap(E, O);
      } else {
        int last = pop_back(E);
        int newE = merge(O, last);
        O = E;
        E = newE;
      }
    }
  }
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  int T = 1;
  // std::cin >> T;

  for (int Ti = 0; Ti < T; Ti++) {
    solve();
  }

  return 0;
}

第4题 A-4 Stop Blowing, Wind of Longing

image

思路

dijkstra两遍,第一遍尝试不经过"想你的风还是吹到了xx"的地点,此时dijkstra的时候要注意如果有多条最短路时,要走经过地点最多的路。如果第一次dijkstra的结果是无法到达,那么进行第二次dijkstra,这次的dijkstra允许经过"想你的风还是吹到了xx"的地点,同样的,如果如果有多条最短路时,要走经过"想你的风还是吹到了xx"地点最少的路。最后按要求输出答案即可。

我的AC代码

#include <bits/stdc++.h>

constexpr int inf = 2E9;

void solve() {
  int n, m;
  std::cin >> n >> m;

  std::vector<std::vector<std::array<int, 2>>> adj(n + 1);
  for (int i = 0; i < m; i++) {
    int u, v, w;
    std::cin >> u >> v >> w;

    adj[u].push_back({v, w});
    adj[v].push_back({u, w});
  }

  int t;
  std::cin >> t;

  std::vector<bool> is(n + 1);
  for (int i = 0; i < t; i++) {
    int x;
    std::cin >> x;
    is[x] = true;
  }

  int st, ed;
  std::cin >> st >> ed;

  auto dijkstra1 = [&]() {
    std::vector<int> dist(n + 1, inf);
    std::vector<int> cnt(n + 1);
    std::vector<bool> vis(n + 1);

    using Node = std::array<int, 2>;
    std::priority_queue<Node, std::vector<Node>, std::greater<>> heap;
    heap.push({0, st});
    dist[st] = 0;
    if (is[st]) {
      return std::array{inf, -1};
    }
    cnt[st] = 1;

    while (heap.size()) {
      auto [distance, u] = heap.top();
      heap.pop();

      if (vis[u]) {
        continue;
      }
      vis[u] = true;

      for (const auto& [v, w] : adj[u]) {
        if (is[v]) {
          continue;
        }
        if (distance + w < dist[v]) {
          dist[v] = distance + w;
          cnt[v] = cnt[u] + 1;
          heap.push({dist[v], v});
        } else if (distance + w == dist[v]) {
          cnt[v] = std::max(cnt[v], cnt[u] + 1);
        }
      }
    }

    return std::array{dist[ed], cnt[ed]};
  };

  auto [dist1, cnt1] = dijkstra1();

  if (dist1 != inf) {
    std::cout << dist1 << " " << cnt1 << "\n";
    return;
  }

  auto dijkstra2 = [&]() {
    std::vector<int> dist(n + 1, inf);
    std::vector<int> cnt(n + 1);
    std::vector<bool> vis(n + 1);

    using Node = std::array<int, 2>;
    std::priority_queue<Node, std::vector<Node>, std::greater<>> heap;
    heap.push({0, st});
    dist[st] = 0;
    cnt[st] = (is[st] ? 1 : 0);

    while (heap.size()) {
      auto [distance, u] = heap.top();
      heap.pop();

      if (vis[u]) {
        continue;
      }
      vis[u] = true;

      for (const auto& [v, w] : adj[u]) {
        if (distance + w < dist[v]) {
          dist[v] = distance + w;
          if (is[v]) cnt[v] = cnt[u] + 1;
          else cnt[v] = cnt[u];
          heap.push({dist[v], v});
        } else if (distance + w == dist[v]) {
          if (is[v]) cnt[v] = std::min(cnt[v], cnt[u] + 1);
          else cnt[v] = std::min(cnt[v], cnt[u]);
        }
      }
    }

    return std::array{dist[ed], cnt[ed]};
  };

  auto [dist2, cnt2] = dijkstra2();

  std::cout << dist2 << " " << cnt2 << "\n";
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);

  int T = 1;
  // std::cin >> T;

  for (int Ti = 0; Ti < T; Ti++) {
    solve();
  }

  return 0;
}
posted @ 2026-02-26 09:42  Beau_Will  阅读(5)  评论(0)    收藏  举报