首页 > 技术文章 > HDU 5805 NanoApe Loves Sequence (思维题) BestCoder Round #86 1002

Ritchie 2016-08-07 20:24 原文

题目:传送门

题意:题目说的是求期望,其实翻译过来意思就是:一个长度为 n 的数列(n>=3),按顺序删除其中每一个数,每次删除都是建立在最原始数列的基础上进行的,算出每次操作后得到的新数列的相邻两数的差的绝对值的最大值,求这些n个最大值的总和。

题解:把n=3的情况单独拿出来直接算出来,就是abs(data[3]-data[2])+abs(data[2]-data[1])+abs(data[3]-data[1]),然后讨论n>=4的情况。首先遍历求出原始数列的相邻两数的差的绝对值的最大值mx,设这两个相邻的数的下标为mi-1mi,我们在本题中以右边mi基准。然后依次考虑删除mi-1mi这两个点的时候的情况,也就是说求出没有mi-1这个点的时候得到的最大值,再求出没有mi这个点的时候得到的最大值,设他俩分别为mx2mx3,用if continue就可以实现,就是循环到那个点的时候跳过两次就行了,为什么要跳过两次呢?因为删去一个点会影响到他右边这两个数作为基准求最大值的情况,两边所以要跳过两次。这样数据就够用了可以求答案了。

随后考虑把两端的点删除的时候的最大值,不一定是mx+mx,如果mi-1==1或者mi==n要单独考虑初始值,用if判断一下即可,比如 1 7 100 6这组数据就是mi==n的情况,答案是94+99+6+93=292,初始值是94+93=187,也就是mx+mx3,在纸上写一下就很容易明白了。随后进行遍历即可,遍历过程就是考虑在2n-1这些数中依次删去每个数看abs(data[i+1]-data[i-1])是否比现有的最大值还要大,取其中较大值加到ans里即可,但是不要更新最大值,因为那样是不对的,另外注意这里的最大值不是同一个,对于非mimi-1这两个点的点来说最大值是mx,对于mi-1来说最大值是mx2,对于mi来说最大值是mx3。具体过程请看代码,如果有没看懂的或者更好的解决办法欢迎大家留言给我。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <iostream>
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
ll data[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        ll mx=-1,mi=-1,tmp;
        memset(data,-1,sizeof(data));
        for(int i=1; i<=n; i++)
            scanf("%lld",&data[i]);
        ll ans=0;
        if(n==3)
        {
//            cout<<abs(data[3]-data[2])<<endl;
//            cout<<abs(data[3]-data[1])<<endl;
//            cout<<abs(data[2]-data[1])<<endl;
            ans=ans+abs(data[3]-data[2])+abs(data[2]-data[1])+abs(data[3]-data[1]);
            printf("%lld\n",ans);
            continue;
        }
        for(int i=2; i<=n; i++)
        {
            tmp=abs(data[i]-data[i-1]);
            if(tmp>mx)
            {
                mx=tmp;
                mi=i;
            }
        }
        ll mx2=-1,m2i=-1;
        for(int i=2; i<=n; i++)
        {
            if(i==mi-1||i==mi) continue;
            tmp=abs(data[i]-data[i-1]);
            if(tmp>mx2)
            {
                mx2=tmp;
                m2i=i;
            }
        }
        ll mx3=-1,m3i=-1;
        for(int i=2; i<=n; i++)
        {
            if(i==mi+1||i==mi) continue;
            tmp=abs(data[i]-data[i-1]);
            if(tmp>mx3)
            {
                mx3=tmp;
                m3i=i;
            }
        }
        //cout<<mx2<<endl<<mx3<<endl;
        if(mi==n)
        ans=mx+mx3;
        else if(mi==2)
        ans=mx+mx2;
        else
        ans=mx+mx;
        //cout<<ans<<endl;
        for(int i=2; i<=n-1; i++)
        {
            if(i==mi-1)//代表mi-1和mi
            {
                tmp=abs(data[i+1]-data[i-1]);
                if(tmp>mx2)
                    ans+=tmp;
                else
                    ans+=mx2;
            }
            else if(i==mi) //代表mi和mi+1
            {
                tmp=abs(data[i+1]-data[i-1]);
                if(tmp>mx3)
                    ans+=tmp;
                else
                    ans+=mx3;
            }
            else
            {
                tmp=abs(data[i+1]-data[i-1]);
                if(tmp>mx)
                    ans+=tmp;
                else
                    ans+=mx;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

推荐阅读