题解:Luogu P10225 Milano C.le

题目大意

原题链接:P10225 Milano C.le

\(n\) 列火车,每一列有进站序号 \(a\) 和出站序号 \(b\),必须所有列车都进站完毕后才可以依次出站,且两两之间不能相互影响,即不能出现出站序号靠后的火车排在序号靠前的火车前面。求出最少需要几个站台可以满足上述需求。

解题思路

这道题说白了就是一个先进后出的栈思想。

我们可以把所有火车按进站顺序排好序,然后从第一列火车开始进行进站操作。

对于每列火车,如果当前已使用的所有站台中存在某一个站台最前面的火车的出站序号小于当前火车,则该火车可以直接停靠在该站台。如果所有站台都不满足最前面的火车的出站序号小于当前火车,则需要开辟一个新站台来停放该火车。

但是如果每一列火车进站时都要去遍历一遍站台的话,时间复杂度最坏会到 \(n^2\),必然超时。而我们可以发现,每个站台的最前列火车的出站序号是有序的,为什么呢?

因为对于每列火车,只有在所有站台都小于它的出站序列时,它才会开辟一个新站台。所以我们通过二分查找找出满足需求的最小站台,将该列车放进去,就能保证不破坏有序性。

参考代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
struct tr {
  ll a, b;
} g[N];
ll sum[N], n, res, cnt; //sum表示站台,cnt表示已使用的站台数量

bool cmp(tr &x, tr &y) { return x.a < y.a; }
bool check(ll m) {}
int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) cin >> g[i].a;
  for (int i = 1; i <= n; i++) cin >> g[i].b;
  sort(g + 1, g + n + 1, cmp);
  sum[++cnt] = g[1].b;
  for (int i = 2; i <= n; i++) {
    ll l = 1, r = cnt, tp = 0; //tp记录正确位置当前元素插入的位置
    while (l <= r) {
      ll m = (l + r) / 2;
      if (sum[m] < g[i].b) l = m + 1;
      else tp = m, r = m - 1;
    }
    if (tp == 0) sum[++cnt] = g[i].b; //开辟新站台
    else sum[tp] = g[i].b;
  }
  cout << cnt;
  return 0;
}
posted @ 2025-02-15 16:47  Duanhen  阅读(26)  评论(0)    收藏  举报