P3195

  • 斜率优化

  • 暴力转移:

    • f(i) 表示考虑到第 i 个玩具达成的最小费用
    • f(i)=min(f(j)+(ij+j+1icL)2)
    • si=1i+i
    • f(i)=min(f(j)+(sisj1L)2)
    • 不妨设 L=L+1
    • f(i)=min(f(j)+(sisjL)2)
  • 消掉常数项 f(j)+(sj+L)22sisj

    • g(i)=f(i)+(si+L)2
  • j<k<if(j)f(k)

    • g(k)2siskg(j)2sisj
    • g(k)g(j)sksj2si
  • 设点 A,B,C=(si,f(i)+(si+L)2)

    • 2si=s0 斜率为 k1,k2
    • s0k1k2 则 A > B > C
    • k2s0k1 则 A, C > B
    • k2k1s0​则 C > B > A
  • 跟 B 始终无关 -> A, C 连边构成下凸包

  • 关于代码

    • Slope(q[l + 1], q[l]) <= 2.0 * sum[i] 说明 q[l + 1] > q[l], 舍弃 q[l]
    • Slope(q[r], q[r - 1]) >= Slope(i, q[r]) 说明 i > q[r] > q[r - 1],舍弃 q[r - 1]
# include <bits/stdc++.h>
# define int long long
# define double long double
using namespace std;
const int MOD = (int)1e9 + 7;
const int N = (int)1e6 + 10;
int n, ll;
int c[N], sum[N];
int q[N], l, r;
int dp[N];
int X(int x){
return sum[x]; //
}
int Y(int x){
return dp[x] + (sum[x] + ll) * (sum[x] + ll);
}
double Slope(int x, int y){
return 1.0 * (Y(x) - Y(y)) / (X(x) - X(y));
}
signed main(){
// freopen("1.in", "r", stdin);
cin >> n >> ll;
for(int i = 1; i <= n; i++){
cin >> c[i];
sum[i] = sum[i - 1] + (c[i] + 1);
}
ll++; // ll 和 1 合并, 见式子
l = 1, r = 1;
q[1] = 0;
for(int i = 1; i <= n; i++){
while(l < r && Slope(q[l + 1], q[l]) <= 2.0 * sum[i]){
l++;
}
int j = q[l];
dp[i] = dp[j] + (sum[i] - sum[j] - ll) * (sum[i] - sum[j] - ll);
while(l < r && Slope(q[r], q[r - 1]) >= Slope(i, q[r])) {
r--;
}
q[++r] = i;
}
cout << dp[n] << "\n";
}

注:a > b 表示 a 比 b 优

posted on   Bubble_e  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话



点击右上角即可分享
微信分享提示