Codeforces Round #344 (Div. 2) E. Product Sum (三分)

本文介绍了一个算法问题,即通过移动数组中的一个元素来最大化数组的特性值(sum(i*a[i]))。通过对每个元素应用三分法来寻找最佳移动位置,最终得到最大可能的特性值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E. Product Sum
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Blake is the boss of Kris, however, this doesn't spoil their friendship. They often gather at the bar to talk about intriguing problems about maximising some values. This time the problem is really special.

You are given an array a of length n. The characteristic of this array is the value  — the sum of the products of the valuesai by i. One may perform the following operation exactly once: pick some element of the array and move to any position. In particular, it's allowed to move the element to the beginning or to the end of the array. Also, it's allowed to put it back to the initial position. The goal is to get the array with the maximum possible value of characteristic.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 200 000) — the size of the array a.

The second line contains n integers ai (1 ≤ i ≤ n|ai| ≤ 1 000 000) — the elements of the array a.

Output

Print a single integer — the maximum possible value of characteristic of a that can be obtained by performing no more than one move.

Examples
input
4
4 3 2 5
output
39
input
5
1 1 2 7 1
output
49
input
3
1 1 2
output
9
Note

In the first sample, one may pick the first element and place it before the third (before 5). Thus, the answer will be3·1 + 2·2 + 4·3 + 5·4 = 39.

In the second sample, one may pick the fifth element of the array and place it before the third. The answer will be1·1 + 1·2 + 1·3 + 2·4 + 7·5 = 49.

题解:给你出n个数,计算sum(i*a[i]) 。然后你可以任意挪动一个数的位置,且只能移动一个数。让你求移动后的最大值sum(i*a[i])。三分。枚举每个数,然后三分移动到各个位置寻求最大值。具体看代码吧。

AC代码:

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#include<set>
#include<stack>
#include <utility> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mst(a) memset(a, 0, sizeof(a))
#define M_P(x,y) make_pair(x,y)
#define in freopen("in.txt","r",stdin) 
#define rep(i,j,k) for (int i = j; i <= k; i++)  
#define per(i,j,k) for (int i = j; i >= k; i--)  
#define lson  l , mid , rt << 1  
#define rson  mid + 1 , r , rt << 1 | 1  
const int lowbit(int x) { return x&-x; }  
const double eps = 1e-8;  
const int INF = 1e9+7; 
const ll inf =(1LL<<62) ;
const int MOD = 1e9+7;  
const ll mod = (1LL<<32);
const int N =2e5+7; 
const int M=100010;
const ll MAX=1e18;
//const int maxn=1001; 
template <class T1, class T2>inline void getmax(T1 &a, T2 b) {if (b>a)a = b;}  
template <class T1, class T2>inline void getmin(T1 &a, T2 b) {if (b<a)a = b;}
int read(){
int v = 0, f = 1;char c =getchar();
while( c < 48 || 57 < c ){if(c=='-') f = -1;c = getchar();}
while(48 <= c && c <= 57) v = v*10+c-48, c = getchar();
return v*f;}

ll a[N],cur;
ll ans1,ans2,sum[N];
ll total;
int n,mid1,mid2;
int Left,Right;

ll calc(int x,int y) //位置x移到位置y
{
    if(x<=y)return total-sum[y]+sum[x]+a[x]*(y-x);
    else return total+sum[x-1]-sum[y-1]+a[x]*(y-x);
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
        total += i*a[i];
    }
    ll ans=-inf;
    for(int i=1;i<=n;i++)
    {
        Left=1; Right=n;
		cur=-inf;
        while(Left+1<=Right)
        {
            mid1=Left+(Right-Left)/3;
            mid2=Right-(Right-Left)/3;
            ans1=calc(i,mid1);
            ans2=calc(i,mid2);
            if(ans1>ans2)
			{
			  	Right=mid2-1;
			  	cur=max(cur,ans1);
			}
            else 
			{
				Left=mid1+1;
				cur=max(cur,ans2);
			}
        }
        cur=max(cur,calc(i,Left));
        if(cur>ans)ans=cur;
    }
    cout<<ans;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值