题意:输入一个长度为n(n <= 10^6)的序列A,找到一个尽量长的连续子序列AL~AR,使得该序列中没有相同的元素。
分析:
法一:从r=0开始不断增加r,当a[r+1]在子序列a[l~r]中出现过,只需增大l,并继续延伸r,因为a[l~r]为可行解,则l增大后必然还是可行解。用set判断a[r+1]是否出现过,并进行a[l]的删除操作。
#pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define Min(a, b) ((a < b) ? a : b) #define Max(a, b) ((a < b) ? b : a) typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const double eps = 1e-8; const int MAXN = 1000000 + 10; const int MAXT = 10000 + 10; using namespace std; int a[MAXN]; set<int> s; int main(){ int T; scanf("%d", &T); while(T--){ s.clear(); int n; scanf("%d", &n); for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); } int l = 0, r = 0, ans = 0; while(r < n){ while(r < n && !s.count(a[r])){ s.insert(a[r++]); } ans = Max(ans, r - l); s.erase(a[l++]); } printf("%d\n", ans); } return 0; }
法二:mp[cur]记录的是元素cur所对应的下标。只要与a[r+1]相同的上一个元素下标小于l,则可延伸,++r,否则++l。
#pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define Min(a, b) ((a < b) ? a : b) #define Max(a, b) ((a < b) ? b : a) typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const double eps = 1e-8; const int MAXN = 1000000 + 10; const int MAXT = 10000 + 10; using namespace std; int a[MAXN], last[MAXN]; map<int, int> mp; int main(){ int T; scanf("%d", &T); while(T--){ mp.clear(); int n; scanf("%d", &n); for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); if(!mp.count(a[i])){ last[i] = -1; } else{ last[i] = mp[a[i]];//前一个大小为a[i]的元素下标 } mp[a[i]] = i;//不断更新大小为a[i]的当前下标 } int l = 0, r = 0, ans = 0; while(r < n){ while(r < n && last[r] < l) ++r; ans = Max(ans, r - l); ++l; } printf("%d\n", ans); } return 0; }