BZOJ1345 Baltic2007 序列问题Sequence 【思维题】*
BZOJ1345 Baltic2007 序列问题Sequence
Description
对于一个给定的序列a1,…,an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列。这一操作的代价是max(ai,ai+1)。进行n-1次该操作后,可以得到一个长度为1的序列。我们的任务是计算代价最小的reduce操作步骤,将给定的序列变成长度为1的序列。
Input
第一行为一个整数n( 1 <= n <= 1,000,000 ),表示给定序列的长度。
接下来的n行,每行一个整数ai(0 <=ai<= 1, 000, 000, 000),为序列中的元素。
Output
只有一行,为一个整数,即将序列变成一个元素的最小代价。
Sample Input
3
1
2
3
Sample Output
5
其实这题比较思维
考虑一个数的贡献
如果他比左/右边的数大,则一定会产生这个数的贡献,并且左右边分别计算
来想想这是为啥,我们只先考虑一边(左边)的情况
如果这个数比左边的数小,那么无论如何这个数不会产生贡献
如果它比左边的数大,那么考虑这个情况
将情况化简成a,b,c三个数,其中我们在对c进行讨论
那么如果a<c,c一定会有c的贡献
如果a>c,这时候我们考虑先合并a,b还是b,c,最后合并a,c的贡献是定值,合并b,c的贡献显然比合并a,b要优秀,所以肯定会先合并b,c,这里产生了c的贡献
所以前面的结论我们证明了
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000010 4 int a[N],n; 5 long long ans=0; 6 int main(){ 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 9 for(int i=2;i<=n;i++)ans+=max(a[i],a[i-1]); 10 printf("%lld",ans); 11 return 0; 12 }