1. 程式人生 > >歷屆試題 連號區間數

歷屆試題 連號區間數

idt eba spell 數字 bar ans 最大 ive scroll

問題描述
小明這些天一直在思考這樣一個奇怪而有趣的問題:
在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代碼:
#include<stdio.h>
#include<stdlib.h> 
#include<stdbool.h>

#define N 50000
#define Min(a,b) (a<b)?(a):(b)
#define Max(a,b) (a>b)?(a):(b)

void input( int * , int );
int spilt( int * , int );

int main(void){
    int n , a[N] = {0};
    scanf("%d", &n );
    input( a , n );
    
    printf("%d\n", spilt( a , n ));
    
    return 0;
}

int spilt( int *a , int n ){
    int i , j , Left , Right , sum = 0 ;
    //Left 最左邊的數 即序列中最小的數
    //Right最右邊的數 即序列中最大的數
    for( i = 0 ; i < n ; i ++ ){
        sum ++ ;
        //單個數時 即為區間為1的連號區間數
        Left = Right = a[i] ;
        for( j = i+1 ; j < n ; j ++ ){
            Left = Min( Left , a[j] );
            Right= Max( Right, a[j] );
            sum += ( Right-Left == j-i );
            //當序列中最大的數減去最小的數 等於序列的長度時 即為連號區間數
        }
    }
    return sum ;
}

void input( int *a , int n ){
    while( n -- ){
        scanf("%d" , a ++ );
    }
}
44 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
}

歷屆試題 連號區間數