Codeforces 660F:Bear and Bowling 4
2016-04-15 13:42
411 查看
F. Bear and Bowling 4
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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.
Examples
input
output
input
output
input
output
Note
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.
题意是给出一组数。可以去掉部分前缀和后缀,要最终求得的数组,其1*val[1]+2*val[2]+3*val[3]...+n*val
值最大。
记pre[i]为val[i]的前缀和。pre2[i]为每一个数值乘以所在位置的值的前缀和。
发现sum(i,j)=pre2[j] - pre2[i-1] - (i-1)*(pre[j] - pre[i-1])。所求的即sum(i,j)的最大值。
然后从小到大枚举右端点j,往前面找i,使得这个i满足,-(i-1)*pre[j]+ (i-1)*pre[i-1]- pre2[i-1]这个值最大。相当于求(-pre[j],1)与(i-1,(i-1)*pre[i-1]-pre2[i-1])的点积。所以可知直接维护前面每一个数据的(i,i*pre[i]-pre2[i])的凸壳。之后二分查找。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define INF 0x333f3f3f
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
const ll mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const double PI = acos(-1.0);
ll n, le, ri;
ll val[maxn], pre[maxn], pre2[maxn], que[maxn];
double sl(int j, int k)
{
double dy = (j*pre[j] - pre2[j]) - (k*pre[k] - pre2[k]);
double dx = (j - k);
return dy / dx;
}
int sear(ll x)
{
int le2 = le, ri2 = ri;
int mid;
while (le2 < ri2 - 1)
{
mid = (le2 + ri2) / 2;
if (sl(que[mid], que[mid - 1])>x)
le2 = mid;
else
ri2 = mid;
}
return que[le2];
}
void solve()
{
ll i, j;
ll res = 0;
scanf("%I64d", &n);
memset(pre, 0, sizeof(pre));
memset(pre2, 0, sizeof(pre2));
for (i = 1; i <= n; i++)
{
scanf("%I64d", &val[i]);
pre[i] = pre[i - 1] + val[i];
pre2[i] = pre2[i - 1] + val[i] * i;
}
le = 0, que[ri] = 0, ri++;
for (i = 1; i <= n; i++)
{
j = sear(pre[i]);
res = max(res, pre2[i] - pre2[j] - j*(pre[i] - pre[j]));
while (le + 1 < ri&&sl(que[ri - 1], que[ri - 2]) < sl(i, que[ri - 1]))
ri--;
que[ri] = i;
ri++;
}
printf("%I64d\n", res);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
#endif
solve();
return 0;
}
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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.
Examples
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
Note
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.
题意是给出一组数。可以去掉部分前缀和后缀,要最终求得的数组,其1*val[1]+2*val[2]+3*val[3]...+n*val
值最大。
记pre[i]为val[i]的前缀和。pre2[i]为每一个数值乘以所在位置的值的前缀和。
发现sum(i,j)=pre2[j] - pre2[i-1] - (i-1)*(pre[j] - pre[i-1])。所求的即sum(i,j)的最大值。
然后从小到大枚举右端点j,往前面找i,使得这个i满足,-(i-1)*pre[j]+ (i-1)*pre[i-1]- pre2[i-1]这个值最大。相当于求(-pre[j],1)与(i-1,(i-1)*pre[i-1]-pre2[i-1])的点积。所以可知直接维护前面每一个数据的(i,i*pre[i]-pre2[i])的凸壳。之后二分查找。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define INF 0x333f3f3f
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
const ll mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const double PI = acos(-1.0);
ll n, le, ri;
ll val[maxn], pre[maxn], pre2[maxn], que[maxn];
double sl(int j, int k)
{
double dy = (j*pre[j] - pre2[j]) - (k*pre[k] - pre2[k]);
double dx = (j - k);
return dy / dx;
}
int sear(ll x)
{
int le2 = le, ri2 = ri;
int mid;
while (le2 < ri2 - 1)
{
mid = (le2 + ri2) / 2;
if (sl(que[mid], que[mid - 1])>x)
le2 = mid;
else
ri2 = mid;
}
return que[le2];
}
void solve()
{
ll i, j;
ll res = 0;
scanf("%I64d", &n);
memset(pre, 0, sizeof(pre));
memset(pre2, 0, sizeof(pre2));
for (i = 1; i <= n; i++)
{
scanf("%I64d", &val[i]);
pre[i] = pre[i - 1] + val[i];
pre2[i] = pre2[i - 1] + val[i] * i;
}
le = 0, que[ri] = 0, ri++;
for (i = 1; i <= n; i++)
{
j = sear(pre[i]);
res = max(res, pre2[i] - pre2[j] - j*(pre[i] - pre[j]));
while (le + 1 < ri&&sl(que[ri - 1], que[ri - 2]) < sl(i, que[ri - 1]))
ri--;
que[ri] = i;
ri++;
}
printf("%I64d\n", res);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
#endif
solve();
return 0;
}
相关文章推荐
- Windows10环境下React Native打包的个人实践
- Windows10环境下React Native打包的个人实践
- Windows10环境下React Native打包的个人实践
- Windows10环境下React Native打包的个人实践
- Windows10环境下React Native打包的个人实践
- textview 计算宽
- iOS常用数学常量宏
- 安卓回调详细解析
- 浅谈Android应用保护(一):Android应用逆向的基本方法
- [BUG] Neutron创建虚拟路由器,端口状态为down,设置路由网关未生效
- Hough变换之直线检测
- linux删除主ip,从ip自动被删除
- Ubuntu下使用MTI(IMU)
- 一个简单的jsp+servlet实例,实现简单的登录
- 前景检测算法_1(codebook和平均背景法)
- 11111
- 姚帅推荐
- leetcode- Plus One
- COMDLL
- CDISC SDTM CM domain 学习笔记