CodeForces 660F Bear and Bowling 4
2016-05-19 13:40
281 查看
Bear and Bowling 4
Submit Status
Description
Limak is an old brown bear. He often goes bowling with his friends. Today he feels really good and tries to beat his own record!
For rolling a ball one gets a score — an integer (maybe negative) number of points. Score for the i-th roll is multiplied by i and
scores are summed up. So, for k rolls with scores s1, s2, ..., sk,
the total score is
. The total score is 0 if
there were no rolls.
Limak made n rolls and got score ai for the i-th
of them. He wants to maximize his total score and he came up with an interesting idea. He can say that some first rolls were only a warm-up, and that he wasn't focused during the last rolls. More formally, he can cancel any prefix and any suffix of the sequence a1, a2, ..., an.
It is allowed to cancel all rolls, or to cancel none of them.
The total score is calculated as if there were only non-canceled rolls. So, the first non-canceled roll has score multiplied by 1, the second one has score multiplied by 2,
and so on, till the last non-canceled roll.
What maximum total score can Limak get?
Input
The first line contains a single integer n (1 ≤ n ≤ 2·105) — the total number of rolls made by
Limak.
The second line contains n integers a1, a2, ..., an (|ai| ≤ 107) —
scores for Limak's rolls.
Output
Print the maximum possible total score after cancelling rolls.
Sample Input
Input
Output
Input
Output
Input
Output
Hint
In the first sample test, Limak should cancel the first two rolls, and one last roll. He will be left with rolls 1, - 3, 7 what gives him the total score 1·1 + 2·( - 3) + 3·7 = 1 - 6 + 21 = 16.
斜率优化dp,搞出递推式,然后用单调队列维护,由于查询的不是单调的,所以用二分来找。
二分写外面的做法
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 10;
LL p[maxn], s[maxn], dp[maxn], x, ans = 0;
int n, a[maxn], b[maxn];
LL dy(int x, int y)
{
return s[x] * x - p[x] - s[y] * y + p[y];
}
bool check(int x, int y, int z)
{
return dy(y, x) * (z - y) <= dy(z, y) * (y - x) ;
}
bool cmp(int x, int y)
{
return s[x] > s[y];
}
void solve(int l, int r)
{
if (l == r) { ans = max(ans, r ? s[r] - s[r - 1] : 0); return; }
int mid = l + r >> 1;
int q = 0, h = -1;
for (int i = l; i <= mid; i++)
{
while (q < h&&check(a[h - 1], a[h], i)) --h;
a[++h] = i;
}
for (int i = mid + 1; i <= r; i++) b[i] = i;
sort(b + mid + 1, b + r + 1, cmp);
for (int i = mid + 1; i <= r; i++)
{
while (q < h&&dy(a[q + 1], a[q]) >= s[b[i]] * (a[q + 1] - a[q])) ++q;
ans = max(ans, dp[b[i]] = p[b[i]] - p[a[q]] - (s[b[i]] - s[a[q]])*a[q]);
}
solve(l, mid); solve(mid + 1, r);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &x);
s[i] = s[i - 1] + x;
p[i] = p[i - 1] + x*i;
}
solve(0, n);
printf("%lld\n", ans);
return 0;
}
Time Limit: 2000MS | Memory Limit: 262144KB | 64bit IO Format: %I64d & %I64u |
Description
Limak is an old brown bear. He often goes bowling with his friends. Today he feels really good and tries to beat his own record!
For rolling a ball one gets a score — an integer (maybe negative) number of points. Score for the i-th roll is multiplied by i and
scores are summed up. So, for k rolls with scores s1, s2, ..., sk,
the total score is
. The total score is 0 if
there were no rolls.
Limak made n rolls and got score ai for the i-th
of them. He wants to maximize his total score and he came up with an interesting idea. He can say that some first rolls were only a warm-up, and that he wasn't focused during the last rolls. More formally, he can cancel any prefix and any suffix of the sequence a1, a2, ..., an.
It is allowed to cancel all rolls, or to cancel none of them.
The total score is calculated as if there were only non-canceled rolls. So, the first non-canceled roll has score multiplied by 1, the second one has score multiplied by 2,
and so on, till the last non-canceled roll.
What maximum total score can Limak get?
Input
The first line contains a single integer n (1 ≤ n ≤ 2·105) — the total number of rolls made by
Limak.
The second line contains n integers a1, a2, ..., an (|ai| ≤ 107) —
scores for Limak's rolls.
Output
Print the maximum possible total score after cancelling rolls.
Sample Input
Input
6 5 -1000 1 -3 7 -8
Output
16
Input
5 1000 1000 1001 1000 1000
Output
15003
Input
3 -60 -70 -80
Output
0
Hint
In the first sample test, Limak should cancel the first two rolls, and one last roll. He will be left with rolls 1, - 3, 7 what gives him the total score 1·1 + 2·( - 3) + 3·7 = 1 - 6 + 21 = 16.
斜率优化dp,搞出递推式,然后用单调队列维护,由于查询的不是单调的,所以用二分来找。
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int maxn = 2e5 + 10; LL p[maxn], s[maxn], x, dp[maxn]; int n, a[maxn], q = 0, h = -1; LL dy(int x, int y) { return s[x] * x - p[x] - s[y] * y + p[y]; } bool check(int x, int y, int z) { return dy(y, x) * (z - y) <= dy(z, y) * (y - x) ; } LL get(int x, int l, int r) { if (l == r) return p[x] - p[a[l]] - (s[x] - s[a[l]])*a[l]; int q = l, h = r - 1, g = l; while (q <= h) { int mid = q + h >> 1; if (dy(a[mid + 1], a[mid]) >= s[x] * (a[mid + 1] - a[mid])) { g = mid + 1; q = mid + 1; } else h = mid - 1; } return p[x] - p[a[g]] - (s[x] - s[a[g]])*a[g]; } int main() { scanf("%d", &n); LL ans = a[++h] = dp[0] = 0; for (int i = 1; i <= n; i++) { scanf("%lld", &x); s[i] = s[i - 1] + x; p[i] = p[i - 1] + x*i; ans = max(ans, dp[i] = get(i, q, h)); while (q < h&&check(a[h - 1], a[h], i)) --h; a[++h] = i; } printf("%lld\n", ans); return 0; }
二分写外面的做法
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 10;
LL p[maxn], s[maxn], dp[maxn], x, ans = 0;
int n, a[maxn], b[maxn];
LL dy(int x, int y)
{
return s[x] * x - p[x] - s[y] * y + p[y];
}
bool check(int x, int y, int z)
{
return dy(y, x) * (z - y) <= dy(z, y) * (y - x) ;
}
bool cmp(int x, int y)
{
return s[x] > s[y];
}
void solve(int l, int r)
{
if (l == r) { ans = max(ans, r ? s[r] - s[r - 1] : 0); return; }
int mid = l + r >> 1;
int q = 0, h = -1;
for (int i = l; i <= mid; i++)
{
while (q < h&&check(a[h - 1], a[h], i)) --h;
a[++h] = i;
}
for (int i = mid + 1; i <= r; i++) b[i] = i;
sort(b + mid + 1, b + r + 1, cmp);
for (int i = mid + 1; i <= r; i++)
{
while (q < h&&dy(a[q + 1], a[q]) >= s[b[i]] * (a[q + 1] - a[q])) ++q;
ans = max(ans, dp[b[i]] = p[b[i]] - p[a[q]] - (s[b[i]] - s[a[q]])*a[q]);
}
solve(l, mid); solve(mid + 1, r);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &x);
s[i] = s[i - 1] + x;
p[i] = p[i - 1] + x*i;
}
solve(0, n);
printf("%lld\n", ans);
return 0;
}
相关文章推荐
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- CodeForces 449A - Jzzhu and Chocolate
- CodeForces 449 B. Jzzhu and Cities
- codeforces 618C. Constellation
- Codeforces Round #349 (Div. 2) - C
- Codeforces Round #265 (Div. 2)
- Codeforces #310 div2 C. Case of Matryoshkas
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces Round332 部分题解
- CodeForces 603A_Alternative Thinking (DP)
- CodeForces 602B_Approximating a Constant Range_DP
- Codeforces round #247 for Div. 2
- Codeforces Round #246 (Div. 2)
- Codeforces #264(div 2)D.Gargari and Permutations
- Codeforces Round #236 (Div. 2)------A,B
- codeforces 257 div2 B