怀特先生是一名研究地震的科学家,最近他发现如果知道某一段时间内的地壳震动能量采样的最小波动值之和,可以有效地预测大地震的发生。
假设已知一段时间的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
有点难想到,用模拟链表的方法才能过,STL的set都超时,做法是,将数据排好序之后模拟成链表,再按开始顺序遍历,找到绝对值最小的再删除。
1 #include<stdio.h> 2 #include<math.h> 3 #include<algorithm> 4 using namespace std; 5 6 #define maxn 100000+10 7 const int INF=1000000000; 8 struct Node 9 { 10 int x,p; 11 bool operator <(const Node&b)const 12 {return x<b.x;} 13 }num[maxn]; 14 int n; 15 int c[maxn]; 16 int li[maxn]; 17 int pre[maxn]; 18 int nex[maxn]; 19 20 21 int calc(int x) 22 { 23 int res = INF; 24 if(pre[x]>=1) 25 res = min (res,li[x]-li[pre[x]]); 26 if(nex[x]<=n) 27 res = min (res,li[nex[x]]-li[x]); 28 return res; 29 } 30 31 int main() 32 { 33 while(~scanf("%d",&n)) 34 { 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%d",&num[i].x); 38 num[i].p=i; 39 } 40 sort(num+1,num+n+1); 41 for(int i=1;i<=n;i++) 42 { 43 li[i]=num[i].x; 44 c[num[i].p]=i; 45 pre[i]=i-1; 46 nex[i]=i+1; 47 } 48 int ans=0; 49 for(int i=1;i<n;i++) 50 { 51 ans+=calc(c[i]); 52 pre[nex[c[i]]]=pre[c[i]];//更新链表 53 nex[pre[c[i]]]=nex[c[i]];// 54 } 55 ans +=li[c[n]]; 56 printf("%d ",ans); 57 } 58 return 0; 59 }