您的位置:首页 > 其它

codeforces 631E Product Sum (dp凸单调性)

2016-03-06 10:45 351 查看
<a target=_blank href="http://codeforces.com/problemset/problem/631/E" style="color: rgb(0, 0, 204); margin-top: 0px; font-family: verdana, arial, sans-serif; font-size: 13px; text-align: center;">Product Sum</a>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<bitset>
#include<stack>
using namespace std;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#define inf 0x3f3f3f3f
#define eps 1e-9
#define pii pair<int,int>
#define MP make_pair
#define LL  long long
#define ULL unsigned long long
#define N ( 1000000 + 10 )
#define M ( 200000 + 10)
#define mod  1000000007
/*
i < j
$ans[i][j] = {(i, j-1) | a[i] * (i+1)} + a[j] * i - ( {(i,j-1) | a[i] * i} + a[j] * j);
= a[j] * (i-j) + sum[i][j-1]
= a[j] * i - a[j]*j + s[j-1] - s[i-1];
= a[j] * i - s[i-1] + s[j-1] - a[j]*j; // f[j] = s[j-1] - a[j] * j
= a[j] * i - s[i-1] + f[j]; // g[i]
i1 < i2
a[j] * i1 - s[i1-1] < a[j] * i2 - s[i2-1]
(s[i2-1] - s[i1-1])/(i2-i1) > a[j] // ll(i1, i2)
i1 < i2 < i
ll(i1, i2) >= ll(i2, i)
(s[i2-1] - s[i1-1])/(i2-i1) >= (s[i-1] - s[i2-1]) / (i-i2)
--

#ans[i][j] = {(i+1, j) | a[i] * (i-1)} + a[i] * j - ( {(i+1,j) | a[i] * i} + a[i] * i);
= a[i] * (j-i) - sum[i+1][j]
= a[i] * j - a[i] * i - (s[j] - s[i])
= a[i] * j - s[j] + (-a[i] * i + s[i])  //-f[i] = a[i] * i - s[i]
= a[i] * j - s[j] - f[i]; // g[j]
j1 < j2
g[j1] > g[j2]
a[i] * j1 - s[j1] - f[i] > a[i] * j2 - s[j2] - f[i]
a[i] * j1 - s[j1] > a[i] * j2 - s[j2]
a[i] * (j1-j2) > s[j1] - s[j2]
(s[j1] - s[j2])/(j1-j2) < a[i] //ll(j2, j1)
j < j1 < j2
ll(j1, j) >= (j2, j1)
(s[j] - s[j1])/(j-j) >= (s[j1] - s[j2])/(j1-j2)

>    >
ans = max(max(#ans[i]) + init)
*/

int a
;
LL sum
;
int tot;
struct point{
LL a, s;
LL get(int i) {
return a * i - s;
}
};
point que
;
bool judge(point i1, point i2, point i) {
return (i.s - i2.s) * (i2.a - i1.a) <= (i2.s - i1.s) * (i.a - i2.a);
}
void insert(LL a, LL s) {
point tmp;
tmp.a = a, tmp.s = s;
while(tot >= 2 && judge(que[tot-2], que[tot-1], tmp))
--tot;
que[tot++] = tmp;
}

LL query(int x) {
int l = -1, r = tot-1;
while(r-l>1) {
int mid = l+r>>1;
if(que[mid].get(x) <= que[mid+1].get(x))
l = mid;
else r = mid;
}
return que[r].get(x);
}

int main() {
int n;
scanf("%d", &n);
LL ans = 0, init= 0;
sum[0] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
init += (LL)a[i] * i;
sum[i] = sum[i-1] + a[i];
}
tot = 0;
for(int i = 2; i <= n; ++i) {
insert(i-1, sum[i-2]);
ans = max(ans, query(a[i]) + sum[i-1] - (LL)a[i] * i);
}
tot = 0;
for(int i = n-1; i >= 1; --i) {
insert(-(i+1), sum[i+1]);
ans = max(ans, query(-a[i]) - (LL)a[i] * i + sum[i]);
}
printf("%I64d\n", ans + init);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: