1 条题解

  • 0
    @ 2026-5-5 22:59:02

    1237B1237B - 平衡隧道

    这个问题可以通过多种方法解决,以下是其中一种。

    假设汽车在时间点 1,2,,n1,2,\dots,n 离开隧道,并设 cic_i 为汽车 aia_i 离开隧道的时间。

    例如,在第一个示例中,我们有 a=3,5,2,1,4a = \langle 3,5,2,1,4 \rangleb=4,3,2,5,1b = \langle 4,3,2,5,1 \rangle。那么 c=2,4,3,5,1c = \langle 2,4,3,5,1 \rangle:汽车 33 第一个进入并在时间 22 离开,所以 c1=2c_1 = 2;汽车 55 第二个进入并在时间 44 离开,所以 c2=4c_2 = 4;依此类推。

    注意 cc 是一个排列,它不仅可以在 O(n)O(n) 时间内找到,而且对我们非常有用。结果表明,我们可以使用 cc 轻松判断汽车 aia_i 是否必须被罚款。

    具体来说,如果 cic_i 小于 max(c1,c2,,ci1)\max(c_1, c_2, \dots, c_{i-1}),则汽车 aia_i 必须被罚款。

    为什么呢?回顾一下:如果存在一辆更早进入隧道并且更晚离开隧道的汽车,那么汽车 aia_i 就必须被罚款。如果有一辆车更早进入隧道,那它一定是某个 aja_jj<ij < i。如果它更晚离开隧道,则必须满足 cj>cic_j > c_i

    因此,现在我们只需从左到右遍历,维护 c1,c2,,ci1c_1, c_2, \dots, c_{i-1} 的最大值,并将其与 cic_i 进行比较。总复杂度为 O(n)O(n)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(0);
      int n;
      cin >> n;
      vector<int> a(n), b(n);
      for (int i = 0; i < n; i++) {
        cin >> a[i];
        --a[i];
      }
      for (int i = 0; i < n; i++) {
        cin >> b[i];
        --b[i];
      }
      vector<int> pos(n);
      for (int i = 0; i < n; i++) {
        pos[b[i]] = i;
      }
      vector<int> c(n);
      for (int i = 0; i < n; i++) {
        c[i] = pos[a[i]];
      }
      int mx = -1, ans = 0;
      for (int i = 0; i < n; i++) {
        if (c[i] > mx) {
          mx = c[i];
        } else {
          ++ans;
        }
      }
      cout << ans << '\n';
      return 0;
    }
    
    • 1

    信息

    ID
    6974
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者