B. Uniqueness(尺取)
You are given an array a1,a2,…,ana1,a2,…,an. You can remove at most one subsegment from it. The remaining elements should be pairwise distinct.
In other words, at most one time you can choose two integers ll and rr (1≤l≤r≤n1≤l≤r≤n) and delete integers al,al+1,…,aral,al+1,…,ar from the array. Remaining elements should be pairwise distinct.
Find the minimum size of the subsegment you need to remove to make all remaining elements distinct.
The first line of the input contains a single integer nn (1≤n≤20001≤n≤2000) — the number of elements in the given array.
The next line contains nn spaced integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) — the elements of the array.
Print a single integer — the minimum size of the subsegment you need to remove to make all elements of the array pairwise distinct. If no subsegment needs to be removed, print 00.
3 1 2 3
0
4 1 1 2 2
2
5 1 4 1 4 9
2
In the first example all the elements are already distinct, therefore no subsegment needs to be removed.
In the second example you can remove the subsegment from index 22 to 33.
In the third example you can remove the subsegments from index 11 to 22, or from index 22 to 33, or from index 33 to 44.
题目链接:http://codeforces.com/contest/1208/problem/B
题解:建立一个map,来记录某个值出现的次数。先从后往前遍历,找到第一个重复的值,记录该位置。然后,从前后遍历,如果当前的这个值在后面出现过,我就需要找到后米娜那个值出现的位置,然后记录最小值,重复操作n次。还是看代码理解把。。。
#include <iostream> #include <cstdio> #include <map> using namespace std; const int maxn = 2e3+7; map<int, int> mp; int arr[maxn]; int main() { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &arr[i]); } int j = n; while(j >= 1) { //找到第一个重复的值的位置 if(mp[arr[j]] >= 1) { break; } mp[arr[j]]++; j--; } int ans = INT_MAX; for(int i = 1; i <= n; i++) { ans = min(ans, j - i + 1); mp[arr[i]]++; while(mp[arr[i]] >= 2 && j <= n) { //找到后面这段中已经匹配过,且与当前值相同数的位置 j++; mp[arr[j]]--; } if(mp[arr[i]] >= 2) { //如果前面的操作都做完了,还有相同的值,就需要跳出,可以看下面这组样例来模拟 //6 //9 6 4 4 9 4 break; } } printf("%d\n", ans); return 0; }