POJ 3320 Jessica's Reading Problem (尺取)
Description
给出一段长度为\(n\)的整数序列,求包含所有出现过的数的连续区间的最小长度。
Input
第一行给出序列长度\(n\),第二行给出\(n\)个整数,表示这个序列。\(n \leqslant 10^6\)。
Output
输出一个整数,表示满足条件的区间的最小长度。
Sample Input
5
1 8 8 8 1
Sample Output
2
Solution
求连续区间,尺取问题。限制条件是下限,区间要包含每一种数。依次推进左端点,对于每个左端点,右端点向右直到找到第一个满足条件的位置,更新答案。如果右端点直到最右端仍然找不到合法区间,就跳出。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
int a[N];
map<int, int> mp;
int main()
{
int n;
scanf("%d", &n);
mp.clear();
for (int i = 1; i <= n; i++) scanf("%d", a + i), mp[a[i]]++;
int sum = mp.size();
mp.clear();
int r = 1, cnt = 0, ans = INF;
for (int l = 1; l <= n; l++)
{
while (r <= n && cnt < sum)
{
mp[a[r]]++;
if (mp[a[r]] == 1) cnt++;
r++;
}
if (cnt < sum) break;
ans = min(ans, r - l);
mp[a[l]]--;
if (mp[a[l]] == 0) cnt--;
}
printf("%d\n", ans);
return 0;
}