【 问题描述 】
有N辆列车,标记为1,2,3,…,N。它们按照一定的次序进站,站台共有K个轨道,轨道遵从 先进先出的原则。列车进入站台内的轨道后可以等待任意时间后出站,且所有列车不可后退。现在要使出站的顺序变为N,N-1,N-2,…,1,询问K的最小值是多少。
例如下图中进站的顺序为1,3,2,4,8,6,9,5,7,则出站的顺序变为9,8,7,6,5,4,3,2,1。
【 输入格式 】
输入文件名为manage.in。
输入共2行。
第 1 行包含1个正整数N,表示N辆列车。
第 2 行包含N个正整数,为1至N的一个排列,表示进站次序。
【 输出格式 】
输出文件名为manage.out。
输出共1行,包含1个整数,表示站台内轨道数K的最小值。
【 输入输出样例1 】
manage.in
3
1 2 3
manage.out
3
【 输入输出样例2 】
manage.in
9
1 3 2 4 8 6 9 5 7
manage.out
5
【 数据规模与约定 】
对于30%的数据,N≤10;
对于70%的数据,N≤2000;
对于100%的数据,N≤100000。
分析:我O(N^2)的算法竟然A掉了,这数据......
我的做法是每次在已经有列车的轨道上找轨道上最后的比当前标号大的,如果有,就放在它的后边,否则再单开一个轨道。这样的原理是i>j,i要在j之前出来,那么i一定不能放在j后面,所以j就放在i后面就可以了.利用树状数组可以优化到O(NlogN).
正解是LIS,和序这道题差不多,把不能放在一起的特征找到.这道题中如果i在j前并且i<j,那么i,j一定不会放在同一轨道上,那么O(NlogN)求出LIS就可以了,然而没我的暴力跑得快233.
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; int n, a[100010], b[100010], cnt; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); b[++cnt] = a[1]; for (int i = 2; i <= n; i++) { bool flag = false; for (int j = 1; j <= cnt; j++) { if (b[j] > a[i]) { b[j] = a[i]; flag = true; break; } } if (!flag) b[++cnt] = a[i]; } printf("%d ", cnt); return 0; }