传送门:http://codeforces.com/problemset/problem/855/B
emmmmmm……n比较打,1e15直接暴力的话会T,还有要注意的一点就是选取的ai,aj,ak,下标满足i<=j<=k,orz做的时候没注意WA了好多次orz
这里要用到的是简单的DP,循环扫2遍分别从头到尾,从尾到头记录至今为止的最大最小值,(因为要求pai+qaj+rak的最大值,所以只需要p,q,r>0时*最大值,<0时*最小值就好了,问题就在于如何处理下标不交叉的问题,dp的思想就是用来处理下标和最值之间的问题)从头到尾扫一遍记录的是ai在取aj时的值,从尾到头记录的是ak在取aj时的值,然后只需要再扫一遍记录到i处pai+qaj+rak的最大值就可以了。
#include<iostream> #include<string> #include<string.h> #include<cmath> #include<algorithm> #include<map> using namespace std; typedef long long ll; ll a[100005]; int n, p[3]; ll maxx1[100005], minn1[100005]; ll maxx2[100005], minn2[100005]; int main() { cin >> n; cin >> p[0] >> p[1] >> p[2]; for (int i = 1; i <= n; i++) cin >> a[i]; minn1[0]=1e18; maxx1[0] = -1e18; minn2[n + 1] = 1e18; maxx2[n + 1] = -1e18; for (int i = 1; i <= n; i++) { maxx1[i] = max(maxx1[i - 1], a[i]); minn1[i] = min(minn1[i - 1], a[i]); } for (int i = n; i >= 1; i--) { maxx2[i] = max(maxx2[i + 1], a[i]); minn2[i] = min(minn2[i + 1], a[i]); } ll ans = -4e18; for (int i = 1; i <= n; i++) { ll tmp = 0; if (p[0] >= 0) tmp += p[0] * maxx1[i]; else tmp += p[0] * minn1[i]; if (p[2] >= 0) tmp += p[2] * maxx2[i]; else tmp += p[2] * minn2[i]; ans = max(ans, tmp + p[1] * a[i]); } cout << ans << endl; return 0; }