地震预测

怀特先生是一名研究地震的科学家,最近他发现如果知道某一段时间内的地壳震动能量采样的最小波动值之和,可以有效地预测大地震的发生。

假设已知一段时间的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
map的用法参见http://blog.sina.com.cn/s/blog_49c5866c0100eyh0.html
这题是方法说白了就是从后往前。
比如题目的数据2 0 3 10
sum为和
3和10最后两位直接处理完按照大小形成一个虚拟3 10  sum=17
0插入到这个序列中 0 3 10 
比较0的前后减去0的绝对值谁比较小,取小的那个。 取3  sum=20
然后放入2 形成0 2 3 10  比较前后
2-0>3-2 取1  sum=21
使用map的原因是由于map有序。。。。。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
map<int,int>dd;
int main()
{int a[100100];
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int i;
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        dd[a[n-1]]=n-1;
        dd[a[n-2]]=n-2;
        int sum=a[n-1]+abs(a[n-1]-a[n-2]);
        for(int i=n-3;i>=0;i--)
        {
            if(!dd.count(a[i]))
            {
                dd[a[i]]=i;
            }
            else
                continue;
            map<int,int>::iterator t=dd.find(a[i]);
            map<int,int>::iterator next=++t;
            map<int,int>::iterator fron;
             t--;
            if(t!=dd.begin())
            {
                fron=--t;
                t++;
            }
            else
            {
                fron=t;
            }
            int minn;
            if(next==dd.end())
            {
                minn=t->first-fron->first;
            }
            else if(t==dd.begin())
            {
                minn=next->first-t->first;
            }
            else
            {
                minn=next->first-t->first;
                if(minn>(t->first-fron->first))
                    minn=t->first-fron->first;
                //minn=min(next->first-t->first,t->first-fron->first);
            }
            sum+=minn;
        }
        printf("%d\n",sum);
          dd.clear();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值