cf1208B B. Uniqueness

B. Uniqueness
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a1,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 l and r (1≤l≤r≤n) and delete integers al,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.

Input
The first line of the input contains a single integer n (1≤n≤2000) — the number of elements in the given array.

The next line contains n spaced integers a1,a2,…,an (1≤ai≤109) — the elements of the array.

Output
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 0.

Examples
input

3
1 2 3
output
0
input
4
1 1 2 2
output
2
input
5
1 4 1 4 9
output
2
Note
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 2 to 3.

In the third example you can remove the subsegments from index 1 to 2, or from index 2 to 3, or from index 3 to 4.
題意: 給出n個數字,找出最小的一端連續區間進行刪除操作,使其剩餘元素不含重複元素,求要刪除的最小區間長度。
思路: 逆向考慮問題,要刪除的最少區間長度對應最多能保留多少個數,又因爲區間要是連續的,所以只能刪除左端區間,或中區間,或右邊區間。利用兩個map,第一個存從左往右能保留的每個元素的下標,並用一個數記錄最終下標;第二個map從右往左掃描,用於記錄當前元素的右半部分能保留多少數,如果出現與其右部分的重複元素,則計算其中間要刪除的元素個數,並判斷是否要更新答案,否則進行標記,若當前右半部分的元素與一開始左半部分的元素,則模擬對左半部分元素刪除操作,同時更新刪除元素個數找出最佳答案,具體情況看代碼和註釋。

#include <bits/stdc++.h>
using namespace std;
map<int, int > book1, book2;
int main() {
	int n;
	int a[2005];
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	int ans = 99999;
	// p記錄左半部分能保留數字的下標(即個數), q記錄右半部分能保留到的下標,q-p則爲要刪除的序列的大小 
	int p = 1, q = n; 
	// 從左往右掃描,記錄從左往右能保留多少個數,即遇到重複數字停止掃描 
	while (p <= n) {
		if (book1[a[p]]) {
			break;
		} else {
			book1[a[p]] = p;
		}
		p++;
	}
	// 由於掃描的時候是判斷下一位,所以p要減一纔是實際最後那個不重複元素的下標(個數) 
	p--;
	ans = n - p; // 此時要刪除的元素爲元素總個數減去前左半部分要保留的數字 
	// 從右往左掃描 
	while (q >= 1) {
		if (book2[a[q]]) { // 如果q右半部分的數字在左半部分沒出現過,但q右半部分的數字出現重複,則進行判斷後結束掃描 
			if (ans > q - p) ans = q - p; // 如果此時要刪除的元素個數比之前少,則更新答案 
			break;
		} else { // 否則進行標記該元素出現過 
			book2[a[q]] = 1;
		}
		if (book1[a[q]] && p >= book1[a[q]]) { // 如果右半部分的最左端的元素與一開始左半部分要保留的數字重複,
		//則模擬左半部分元素刪除操作,同時判斷是否要更新答案和更新左半部分要保留的數字下標 
			if (ans > q - p) ans = q - p;
			p = book1[a[q]] - 1;
		}
		q--;
	} 
	printf("%d\n", ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章