题目点此跳转
思路
题目意思是输入一个长度为n(n≤106)的序列A,找到一个尽量长的连续子序列 AL~AR ,使得该序列中没有相同的元素。
首先定义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;
}