题目
Alice and Bob are playing yet another card game. This time the rules are the following. There are cards lying in a row in front of them. The -th card has value .
First, Alice chooses a non-empty consecutive segment of cards (). After that Bob removes a single card from that segment . The score of the game is the total value of the remaining cards on the segment . In particular, if Alice chooses a segment with just one element, then the score after Bob removes the only card is .
Alice wants to make the score as big as possible. Bob takes such a card that the score is as small as possible.
What segment should Alice choose so that the score is maximum possible? Output the maximum score.
输入
The first line contains a single integer () — the number of cards.
The second line contains integers () — the values on the cards.
Code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <stack>
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
#define endl '\n'
#define pb push_back
#define NO cout << "NO" << endl;
#define YES cout << "YES" << endl;
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
typedef vector<int> VI;
typedef pair<int,int> PII;
ll MOD;
ll powmod(ll a,ll b) {ll res=1;a%=MOD; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
mt19937 mrand(random_device{}());
const int N = 2e5 + 10;
int a[N], L[N], R[N], b[N], s[N];
int stk[N], que;
int st[N][21], lg[N], lk[N][21];
int n;
void init() {
for(int i = 1; i <= n + 1; i++) {
st[i][0] = s[i - 1];
lk[i][0] = a[i - 1];
if(i >= 2) {
lg[i] = lg[i / 2] + 1;
}
}
for(int j = 1; j < 21; j++) {
for(int i = 1; i + (1 << j) - 1 <= n + 1; i++) {
st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
lk[i][j] = max(lk[i][j - 1], lk[i + (1 << (j - 1))][j - 1]);
}
}
}
ll calc(int l, int r) {
if(l > r) return 0;
int t = lg[r - l + 1];
return min({st[l][t], st[r - (1 << t) + 1][t]});
}
ll check(int l, int r) {
int t = lg[r - l + 1];
return max(lk[l][t], lk[r - (1 << t) + 1][t]);
}
void solve()
{
cin >> n;
rep(i, 1, n) cin >> a[i];
rep(i, 1, n) s[i] = s[i - 1] + a[i];
a[0] = -1e9;
init();
for(int i = 1; i <= n; i++) {
int l = 0, r = i;
while(l <= r) {
int mid = l + r >> 1;
if(check(mid + 1,i + 1) <= a[i]) r = mid - 1;
else l = mid + 1;
}
// cout << l << ' ';
if(l != i) {
L[i] = s[i - 1] - calc(l + 1, i) ;
}
}
reverse(a + 1, a + 1 + n);
rep(i, 1, n) s[i] = s[i - 1] + a[i];
// rep(i, 1, n) cout << a[i] << " \n"[i == n];
init();
for(int i = 1; i <= n; i++) {
int l = 0, r = i;
ll ans = 0;
while(l <= r) {
int mid = l + r >> 1;
if(check(mid + 1,i + 1) <= a[i]) r = mid - 1;
else l = mid + 1;
}
// cout << l << " \n"[ i == n];
if(l != i) {
R[i] = s[i - 1] - calc(l + 1, i) ;
}
}
// rep(i, 1, n) cout << L[i] << " \n"[ i == n ];
// rep(i, 1, n) cout << R[i] << " \n"[ i == n ];
ll res = 0;
rep(i, 1, n) res = max(res, L[i] + R[n - i + 1]);
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
// int T;cin >> T;
// while ( T -- )
solve();
return 0;
}