问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。
输出格式
输出一个整数,表示不同连号区间的数目。
样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9
AC代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<stdbool.h> 4 5 #define N 50000 6 #define Min(a,b) (a<b)?(a):(b) 7 #define Max(a,b) (a>b)?(a):(b) 8 9 void input( int * , int ); 10 int spilt( int * , int ); 11 12 int main(void){ 13 int n , a[N] = {0}; 14 scanf("%d", &n ); 15 input( a , n ); 16 17 printf("%d\n", spilt( a , n )); 18 19 return 0; 20 } 21 22 int spilt( int *a , int n ){ 23 int i , j , Left , Right , sum = 0 ; 24 //Left 最左边的数 即序列中最小的数 25 //Right最右边的数 即序列中最大的数 26 for( i = 0 ; i < n ; i ++ ){ 27 sum ++ ; 28 //单个数时 即为区间为1的连号区间数 29 Left = Right = a[i] ; 30 for( j = i+1 ; j < n ; j ++ ){ 31 Left = Min( Left , a[j] ); 32 Right= Max( Right, a[j] ); 33 sum += ( Right-Left == j-i ); 34 //当序列中最大的数减去最小的数 等于序列的长度时 即为连号区间数 35 } 36 } 37 return sum ; 38 } 39 40 void input( int *a , int n ){ 41 while( n -- ){ 42 scanf("%d" , a ++ ); 43 } 44 }