UVA - 11572 Unique Snowflakes(唯一的雪花) : 滑動窗口

題目點此跳轉

思路

 題目意思是輸入一個長度爲n(n≤106)的序列A,找到一個儘量長的連續子序列ALAR ,使得該序列中沒有相同的元素。

 首先定義L和R表示要找的結果的左右端點,一開始L = R = 0;
 然後我們不斷地增加R,直到不能增加了爲止,不能增加是因爲再增加的話就有相同的元素了;
 這個時候我們維護一下最大值,然後開始增加L,直到將那個使R不能再增加的元素去掉爲止;
 接着我們就又能繼續增加R了,直到R到序列尾。

 我們會有一個直觀的感覺, 這裏的[L, R] 就像一個窗口一樣, 一開始在最左邊,然後不斷地向右邊滑動, 而且不會滑回來,因爲R是不斷增加的,L也是不斷增加的。這大概就是滑動數組了吧。

 還有一點,我們可以用map來預處理出每一位元素上一次出現的位置, 這樣L往後跳的時候就不用一位一位地找了。

代碼

#include <algorithm>
#include <iostream>
#include <sstream>
#include <utility>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cstring>
#include <cstdio>
#include <cmath>
#define met(a,b) memset(a, b, sizeof(a));
#define IN freopen("in.txt", "r", stdin);
#define OT freopen("out.txt", "w", stdout);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e6 + 100;
const int INF = 0x7fffffff;
const int dir[5][2] = {0,0,-1,0,1,0,0,-1,0,1};
const LL MOD = 1e9 + 7;

int n, a[maxn];
int pre[maxn];
map<int, int> m;

int main() {
    #ifdef _LOCAL
    IN; //OT;
    #endif // _LOCAL

    int t; cin >> t;
    while(t--) {
        scanf("%d", &n); m.clear();
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for(int i = 1; i <= n; ++i) {
            if(!m.count(a[i])) pre[i] = -1;
            else pre[i] = m[a[i]];
            m[a[i]] = i;
        }
        int L = 1, R = 1, ans = 0;
        while(R <= n) {
            while(R+1 <= n && pre[R+1] < L) ++R;
            ans = max(ans, R-L+1); ++R;
            if(R > n) break;
            L = pre[R]+1;
        }
        printf("%d\n", ans);
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章