UVa 11572 - Unique Snowflakes
阿新 • • 發佈:2017-12-22
online style 情況 ont print ans int item std
既然當前的A[L~R]是可行解,L增大之後必然還是可行解,所以不必減少R,繼續增大即可。
可以這樣判斷R是否可以延伸:
用一個map求出 last[i],即下標i的“上一個相同元素的下標”。
例如,輸入序列為3 2 4 1 3 2 3,當前區間是[1,3](即元素2, 4, 1),是否可以延伸呢?
下一個數是A[4]=3,它的“上一個相同位置”是下標0(A[0]=3),不在區間中,因此可以延伸。
鏈接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2619
題意:
輸入一個長度為n(n≤1e6)的序列A,找到一個盡量長的連續子序列A[L]~A[R],使得該序列中沒有相同的元素。
分析:
滑動窗口法。
假設序列元素從0開始編號,所求連續子序列的左端點為L,右端點為R。
首先考慮起點L=0的情況。可以從R=0開始不斷增加R,相當於把所求序列的右端點往右延伸。
當無法延伸(即A[R+1]在子序列A[L~R]中出現過)時,只需增大L,並且繼續延伸R。
既然當前的A[L~R]是可行解,L增大之後必然還是可行解,所以不必減少R,繼續增大即可。
可以這樣判斷R是否可以延伸:
用一個map求出 last[i],即下標i的“上一個相同元素的下標”。
例如,輸入序列為3 2 4 1 3 2 3,當前區間是[1,3](即元素2, 4, 1),是否可以延伸呢?
下一個數是A[4]=3,它的“上一個相同位置”是下標0(A[0]=3),不在區間中,因此可以延伸。
代碼:
1 #include <cstdio> 2 #include <map> 3 using namespace std; 4 5 int main(){ 6 intT; 7 scanf("%d", &T); 8 while(T--){ 9 int n, ans = 0; 10 scanf("%d", &n); 11 map<int,int> last; 12 for(int i, L = 0, R = 1; R <= n; R++){ 13 scanf("%d", &i); 14 if(last[i] > L) L = last[i]; 15 if(ans < R - L) ans = R - L;16 last[i] = R; 17 } 18 printf("%d\n", ans); 19 } 20 return 0; 21 }
UVa 11572 - Unique Snowflakes