P5093 [USACO04OPEN]The Cow Lineup 題解
阿新 • • 發佈:2022-04-17
這道題是一道思維題。
定義『段』如下:
- 段:一個段是原序列的連續子序列,其中 \([1,k]\) 內的所有正整數都出現過。
據此,我們可以對原序列分段,分的儘量多。
比如樣例:
1 5 3 2 5 1 3 4 4 2 5 1 2 3
可以將其分成下面兩段:
[1 5 3 2 5 1 3 4][4 2 5 1 2 3]
我們發現,每一次取每一段的最後一個數字,然後後面在加一個數字就可以構造出要求的子序列。
所以,答案就是段數+1。
Code:
/* ========= Plozia ========= Author:Plozia Problem:P5093 [USACO04OPEN]The Cow Lineup Date:2021/6/7 ========= Plozia ========= */ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAXN = 1e5 + 5, MAXK = 1e4 + 5; int n, k, a[MAXN], ans = 1; queue <int> q[MAXK]; int Read() { int sum = 0, fh = 1; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) fh -= (ch == '-') << 1; for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = sum * 10 + ch - '0'; return sum * fh; } int Max(int fir, int sec) { return (fir > sec) ? fir : sec; } int main() { n = Read(), k = Read(); for (int i = 1; i <= n; ++i) a[i] = Read(); for (int i = 1; i <= n; ++i) q[a[i]].push(i); sort(a + 1, a + n + 1); int cntn = unique(a + 1, a + n + 1) - (a + 1); // /*Debug*/printf("%d\n", cntn); for (int pos = 0; ; ++ans) { bool flag = 0; for (int i = 1; i <= k; ++i) { while (!q[i].empty() && q[i].front() <= pos) q[i].pop(); if (q[i].empty()) { flag = 1; break ; } } if (flag == 1) break ; for (int i = 1; i <= k; ++i) { pos = Max(pos, q[i].front()); } } printf("%d\n", ans); return 0; }