2620 序列问题
对于一个给定的序列a1,a2...ana1,a2...an,我们对它进行一个操作Reduce(i)Reduce(i),
该操作将数列中的元素aiai和ai+1ai+1用一个元素max(aiai,ai+1ai+1)替代,这样得到一
个比原来序列短的新序列。这一操作的代价是max(aiai,ai+1ai+1)。进行n-1次该操作后,
可以得到一个长度为1的序列。我们的任务是计算代价最小的Reduce操作顺序,将给定
的序列变成长度为1的序列。
例如a序列为:1,2,3
那么最优的Reduce顺序为:
首先1,2合并花费为2,序列变为2,3
2,3合并,花费为3,序列变为3,长度为1。
所以答案为5。
输入
第1行:一个整数n表示给定序列的长度。(1 <= n <= 1,000,000 ) 第2到n+1行:每行一个整数a[i]表示序列中的元素。(0 <=a[i]<= 1, 000, 000, 000)输出
输出一个整数表示将序列通过Reduce操作变成一个元素的最小代价。输入样例
3 1 2 3输出样例
5
思路:
19寒假好像做过一个类似的题,没啥印象了.
这题直接考虑了单调性,然后单调栈更新答案,实际上
进一步考虑,只要相邻两个元素(n-1个数对)选大者加入答
案即可。
代码实现:
#include<iostream>
#include<string.h>
#include<math.h>
#include<set>
#include<queue>
#include<stdio.h>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
/*#ifdef MYHOME
freopen("input.txt", "r", stdin);
#endif*/
using namespace std;
const int N = 4e5 + 100;
const int M = 4e5 + 100;
int arr[N];
int main() {
#ifdef MYHOME
freopen("input.txt", "r", stdin);
#endif
int n;
long long ans;
while (cin >> n) {
ans = 0;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
for (int i = 1; i < n; i++) {
ans += max(arr[i], arr[i + 1]);
}
cout << ans << endl;
}
return 0;
}
单调栈代码:
#include<iostream>
#include<string.h>
#include<math.h>
#include<set>
#include<queue>
#include<stdio.h>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
#define ull unsigned long long
/*#ifdef MYHOME
freopen("input.txt", "r", stdin);
#endif*/
using namespace std;
const int N = 4e5 + 100;
const int M = 4e5 + 100;
int arr[N], sc[N],top;
int main() {
#ifdef MYHOME
freopen("input.txt", "r", stdin);
#endif
int n,tmpx,tmpy;
long long ans;
while (cin >> n) {
top = ans = 0;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
for (int i = 1; i <= n; i++) {
if (top && arr[i] >= arr[sc[top]]) top--, ans += arr[i];
sc[++top] = i;
}
top-- ;
while (top > 0) {
ans += arr[sc[top--]];
}
cout << ans << endl;
}
return 0;
}
THE END;