HDU 5805 NanoApe Loves Sequence (思维题) BestCoder Round #86 1002
题目:传送门。
题意:题目说的是求期望,其实翻译过来意思就是:一个长度为 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-1和mi,我们在本题中以右边mi为基准。然后依次考虑删除mi-1和mi这两个点的时候的情况,也就是说求出没有mi-1这个点的时候得到的最大值,再求出没有mi这个点的时候得到的最大值,设他俩分别为mx2和mx3,用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,在纸上写一下就很容易明白了。随后进行遍历即可,遍历过程就是考虑在2到n-1这些数中依次删去每个数看abs(data[i+1]-data[i-1])是否比现有的最大值还要大,取其中较大值加到ans里即可,但是不要更新最大值,因为那样是不对的,另外注意这里的最大值不是同一个,对于非mi和mi-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; }