您的位置:首页 > 产品设计 > UI/UE

(模拟/线段树)HDU - 5805 NanoApe Loves Sequence

2016-08-06 23:01 330 查看

原题链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5805

题意:

给你一个数列,删除其中的一个数,假设删除任意一个数的概率相同,求相邻的数差的绝对值的最大值的期望,题目只要求输出乘概率前的答案。

分析:

模拟:

只需要先求出本身所有相邻数之差的绝对值,找到最大的那个值和它的位置,然后看删除每一个数对他的影响,所有的最大值加起来就行了。

由于每次删除一个数总会失去两种相邻差值绝对值,并获得一种新的相邻差值绝对值,所以影响只有两种情况:

1、删除的数正好在原数列最大值的位置上,那么最大值将改变,在这里可以直接再跑一边for循环找出最大的,因为也只会出现1-2次,所以对整体复杂度没影响,再把新的最大值和新得到的相邻差值绝对值比较一下,就能得出本次最大值。

2、删除的数不在原数列最大值的位置上,这时只需要把原数列的最大值和新得到的相邻差值绝对值比较一下,就能得出最大值。

注:首尾特殊考虑。

线段树:

有个同学写线段树过了,线段树很更加粗暴,对所有差绝对值建一个线段树,每次删除一个就把要失去的两个相邻差值绝对值都变成新得到的相邻差值绝对值,查询完之后再补回来。。首尾同样特殊处理。。虽然跑的慢些,但还是很屌的。- =0=-

线段树代码链接:http://www.cnblogs.com/s1124yy/p/5745028.html

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>

#define ll long long
#define ull unsigned long long

using namespace std;

const int maxn=100010;
const int inf=1<<30;

ll num[maxn];
ll cha[maxn];

int main()
{
//#define DEBUG

#ifdef DEBUG
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif

int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%I64d",&num[i]);
}
ll maxs=-1;
int maxi;
for(int i=0;i<n-1;i++){
cha[i]=abs(num[i]-num[i+1]);
if(maxs<cha[i]){
maxs=cha[i];
maxi=i;
}
}
//printf("i=%d\n",maxi);
ll ans=0;
for(int i=0;i<n;i++){
if(i==0){
if(maxi!=i){
ans+=maxs;
}
else{
ll tmp=-1;
for(int j=1;j<n-1;j++){
tmp=max(tmp,cha[j]);
}
ans+=tmp;
}
}
else if(i==n-1){
if(maxi+1!=i){
ans+=maxs;
}
else{
ll tmp=-1;
for(int j=0;j<n-2;j++){
tmp=max(tmp,cha[j]);
}
ans+=tmp;
}
}
else{
if(maxi==i||maxi+1==i){
ll tmp=-1;
for(int j=0;j<n-1;j++){
if(j==i-1||j==i)continue;
tmp=max(tmp,cha[j]);
}
tmp=max(tmp,abs(num[i+1]-num[i-1]));
ans+=tmp;
}
else{
ans+=max(maxs,abs(num[i+1]-num[i-1]));
}
}
//printf("ans=%I64d\n",ans);
}
printf("%I64d\n",ans);

}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: