Problem Description
怀特先生是一名研究地震的科学家,最近他发现如果知道某一段时间内的地壳震动能量采样的最小波动值之和,可以有效地预测大地震的发生。
假设已知一段时间的n次地壳震动能量的采样值为a1,a2,…an,那么第i 次采样的最小波动值为min{|ai-aj| | i<j<=n},即第i 次采样的最小波动值是其后n-i次采样值与第i次采样值之差的绝对值中最小的值,特别地,第n次采样的最小波动值为an。
请编写一个程序计算这n次采样的最小波动值之和。
Input
本题有多组输入数据,你必须处理到EOF为止
输入数据第一行有一个数n(1<=n<=105) ,表示采样的次数。
第二行有n个整数,表示n次地壳震动能量的采样值a1,a2,…an (0<=ai<=107 )。
Output
输出n次采样的最小波动值之和。
Sample Input
4 2 0 3 10
Sample Output
21
Source
福州大学第四届程序设计竞赛
思路:用数组B[]对原数组A[]进行间接排序,结构Link[],将数组B[]就行链接。C[]记录数组A[]在链表中的位置。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 100001 7 using namespace std; 8 int N; 9 int A[maxn],B[maxn],C[maxn]; 10 struct Link 11 { 12 int left; 13 int right; 14 }Link[maxn]; 15 bool cmp(int i,int j) 16 { 17 return A[i] < A[j]; 18 } 19 int main() 20 { 21 int i,j; 22 while(~scanf("%d",&N)) 23 { 24 for(i=1; i<=N; i++){ 25 scanf("%d",&A[i]); 26 B[i] = i; 27 } 28 sort(B+1,B+N+1,cmp);//间接排序 29 for(i=1; i<=N; i++){ 30 C[B[i]] = i; //记录数组A[i]在有序表中位置 31 Link[i].left = i+1; 32 Link[i].right = i-1; 33 } 34 A[0] = A[N+1] = -1000000000; 35 int sum = 0; 36 for(i=1; i<N; i++){ 37 sum += min( fabs(A[i]-A[B[Link[C[i]].left]]), fabs(A[i]-A[B[Link[C[i]].right]]) ); 38 Link[Link[C[i]].left].right = Link[C[i]].right; 39 Link[Link[C[i]].right].left = Link[C[i]].left; 40 } 41 sum += A[N]; 42 printf("%d ",sum); 43 } 44 return 0; 45 }