题解 CF631E Product Sum
题意
给定一个长度为
数据范围:
题解
考虑先算出未操作时的权值,再去算操作后能使答案增加的最大值。
设
- 当
时, - 当
时,
后面那个求和可以用前缀和弄掉,设
于是我们得到一个
其实化成这样也可以做,但比较麻烦。
观察到上下两个形式很相近,考虑当
发现
于是
拆开后
这个形式显然可以斜率优化,若
维护
-
二分下凸壳,找到比
小的最大斜率。 -
因为答案与计算顺序无关,先将
排序后再上单调队列。
这两种我都写了,二分复杂度
只贴单调队列的代码了。
#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);
}
分类:
未分类
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话