一个数组包含N个正整数,其中有些是重复的。一个前缀后缀集是满足这样条件的下标对(P,S), 0<= P,S < N 满足数组元素A[0..P]的值也在A[S..N - 1]的值中出现,并且A[S..N - 1]中的值也再A[0..P]中出现。换句话说前缀的集合A[0..P]与后缀集合A[S..N - 1]包含完全相同的值。求这样的前缀后缀集合的数量。
例如:3 5 7 3 3 5,共有14个集合符合条件:(1, 4), (1, 3), (2, 2), (2, 1), (2, 0), (3, 2), (3, 1), (3, 0), (4, 2), (4, 1), (4, 0), (5, 2), (5, 1), (5, 0)
本题由 @javaman 翻译。
Input
第1行:一个数N, 表示数组的长度(1 <= N <= 50000)。
第2 - N + 1行:每行1个数,对应数组中的元素Ai。(1 <= Ai <= 10^9)
Output
输出符合条件的集合数量。
Input示例
6
3
5
7
3
3
5
Output示例
14
//似乎简单的贪心就能做,或者说叫枚举,枚举顺序的所有区间
分情况讨论清楚,
1、当顺序是一个已出现的值,累加相同区间个数即可
2、当出现一个新值,map记录一下,不同的值的个数++,然后扩充后缀区间,直到出现新值,或者不同的值个数为0,就可以累加答案了
这样,时间复杂度是 O(n*lgn)
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define eps 1e-9 5 #define LL long long 6 #define MX 50005 7 8 int n; 9 int dat[MX]; 10 LL ans; 11 12 void func() 13 { 14 int R = n, dif = 0, res = 0; 15 map<int,int> mp; 16 for (int i=1;i<=n;i++) 17 { 18 if (mp.count(dat[i])) //如果是重复的,加上个数即可 19 { 20 ans += res; 21 continue; 22 } 23 mp[dat[i]]=1; dif++; 24 res=0; 25 while (R>=1&&mp.count(dat[R])) 26 { 27 if (mp[dat[R]]==1) 28 { 29 mp[dat[R]]=2; 30 dif--; 31 } 32 if (dif==0) 33 { 34 ans++; 35 res++; 36 } 37 R--; 38 } 39 } 40 } 41 42 int main() 43 { 44 while(scanf("%d",&n)!=EOF) 45 { 46 for (int i=1;i<=n;i++) 47 scanf("%d",&dat[i]); 48 ans = 0; 49 func(); 50 printf("%lld ",ans); 51 } 52 return 0; 53 }