题解 CF631E Product Sum

link

题意

给定一个长度为 n 的序列 a,定义该序列的权值为 i=1niai,现有一次将序列中某个数移动到任意位置的机会,可以移回原位,求操作后序列 a 最大权值。

数据范围:2n2×105,|ai|106

题解

考虑先算出未操作时的权值,再去算操作后能使答案增加的最大值。

fi 表示移动 ai 对答案的最大贡献值,若 ai 移到了位置 j,我们分类讨论:

  • i<j 时,fi=max{ai×(ji)k=i+1jak}
  • ij 时,fi=max{k=ji1akai×(ij)}

后面那个求和可以用前缀和弄掉,设 sumi=j=1iaj,则:

fi={max{ai×(ji)sumj+sumi}j(i,n]max{ai×(ji)sumj1+sumi1}j[1,i]

于是我们得到一个 O(n2) 的做法。

其实化成这样也可以做,但比较麻烦。

观察到上下两个形式很相近,考虑当 j[1,i],令 jj1 转化成和上面一样的形式。

fi=max{ai×(ji)sumj1+sumi1}       j[1,i]=max{ai×(j+1i)sumj+sumi1}       j[0,i)=max{ai×(j+1i)sumj+sumiai}       j[0,i)=max{ai×(ji)sumj+sumi}       j[0,i)

发现 j[0,i)j(i,n] 时的计算方式一样,我们便大大简化了过程。

于是 fi=max{ai×(ji)sumj+sumi}

拆开后 fi=max{ai×jsumj}+sumiai×i

这个形式显然可以斜率优化,若 j1<j2i 移到 j2 时比移到 j1 时贡献要大,有:ai×j1sumj1<ai×j2sumj2ai×(j1j2)<sumj1sumj2ai>sumj1sumj2j1j2

维护 (j,sumj) 这些点组成的下凸壳即可,因为点坐标与 fj 无关,可以先把这些点加进来,注意 ai 不一定是单增的,可以有两种处理方式。

  • 二分下凸壳,找到比 ai 小的最大斜率。

  • 因为答案与计算顺序无关,先将 a 排序后再上单调队列。

这两种我都写了,二分复杂度 O(nlogn),排序后单调队列可以用基排做到 O(n),不过我懒得写了,貌似单调队列的做法会快(?

只贴单调队列的代码了。

#include <bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N], head, tail;
ll sum[N], ans, base;
struct node {
    int v, id;
    friend bool operator < (const node &qwq, const node &awa) {
        return qwq.v < awa.v;
    }
} a[N];
ld slope(int i, int j) {
    return (1. * sum[i] - sum[j]) / (i - j);
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i].v);
        sum[i] = sum[i - 1] + a[i].v, base += 1ll * i * a[i].v;
        a[i].id = i;
    }
    head = tail = 1;
    for(int i = 1; i <= n; i++) {
        while(tail > 1 && slope(q[tail - 1], i) < slope(q[tail - 1], q[tail])) tail--;
        q[++tail] = i;
    }
    sort(a + 1, a + 1 + n);
    for(int i = 1; i <= n; i++) {
        while(head < tail && slope(q[head], q[head + 1]) < a[i].v) head++;
        ans = max(ans, 1ll * (q[head] - a[i].id) * a[i].v + sum[a[i].id] - sum[q[head]]);
    }
    printf("%lld\n", ans + base);
}
posted @   Terac  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示