51nod 1280 前缀后缀集合

题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
收藏
关注
一个数组包含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示例


6357335


Output示例


14


思路:正序记录每个位置出现的数字种类数,逆序也记录每个位置的种类数,从大到小枚举种类数,如果种类数减小一,那么判断减去的数字是否相同,不同就跳出。特判1和全部种类数。
PS:数据太弱,不确定是不是正解(刚开始二分查找下标多加了1,竟然只wa一组数据!!!!)

Code:
#include <bits/stdc++.h>
#define INF 1e9
using namespace std;
const int AX = 5e4+66;
int a[AX];
int pre[AX];
int rear[AX]; 
map<int,int>mp;
int main(){
	int n ;
	scanf("%d",&n);
	for( int i = 0 ; i < n ; i++ ){
		scanf("%d",&a[i]);
	}
	memset( pre , 0 ,sizeof(pre) );
	memset( rear , 0 ,sizeof(rear) );
	mp[a[0]] = 1;
	pre[0] = 1;
	for( int i = 1 ; i < n ; i ++ ){
		if( !mp[a[i]] ){
			mp[a[i]] = 1;
			pre[i] = pre[i-1] + 1;
		}else{
			pre[i] = pre[i-1];
		}
	}
	mp.clear();
	mp[a[n-1]] = 1;
	rear[0] = 1;
	for( int i = n - 2 ; i >= 0 ; i -- ){
		if( !mp[a[i]] ){
			mp[a[i]] = 1;
			rear[n-1-i] = rear[n-i-2] + 1 ;
		}else{
			rear[n-1-i] = rear[n-i-2];
		}
	}
	int num = pre[n-1];
	int res = 0;
	int pos1 = lower_bound( pre, pre + n , num )-pre;
	int pos2 = lower_bound( rear , rear + n , num )-rear;
	int id1 = pos1;
	int id2 = pos2;
	int x1 = n - pos1;
	int x2 = n - pos2;
	res += x1 * x2;
	for( int i = num - 1 ; i >= 2 ; i -- ){
		if( a[pos1] == a[n-1-pos2] ){
			pos1 = lower_bound( pre , pre + n , i ) - pre;
			pos2 = lower_bound( rear , rear + n , i ) - rear;
			res += ( pos1 - id1 ) * ( pos2 - id2 );
			id1 = pos1;
			id2 = pos2;	
		}else break;
	}
	pos1 = upper_bound( pre , pre + n , 1 ) - pre;
	pos2 = upper_bound( rear , rear + n , 1 ) - rear;
	if( a[0] == a[n-1] ){
		res += ( pos1 ) * ( pos2 );
	}
	cout << res << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/frankax/article/details/79934921