首页 > 其他分享 >[lnsyoj538/luoguP3628/APIO2010]特别行动队

[lnsyoj538/luoguP3628/APIO2010]特别行动队

时间:2024-07-25 20:07:11浏览次数:16  
标签:int APIO2010 凸包 hh 行动队 luoguP3628 tt dp LL

题意

原题链接
给定序列 \(a\) 和自定义二次函数 \(f(x) = ax^2 + bx + c(a<0)\),要求将 \(a\) 分为几段(不妨设为 \(k\) 段),使得 \(\sum_{i=1}^{k} f(\sum_{j=l_i}^{r_i}a_j)\)的值最大,求最大的值

sol

设计状态转移方程。显然,\(dp_i\) 可以由 \(dp_j\) 转移当且仅当 \(j < i\),这表示从第 \(j + 1\) 到第 \(i\) 个数都被分为一段。容易得到(设 \(S_i = \sum_{j=1}^i a_j\)

\[dp_i = \max_{j=0}^{i-1}\{dp_j + a(S_i-S_j)^2 + b(S_i-S_j) + c \} \]

本题复杂度较高,无法使用 \(O(n^2)\) 的朴素方法 AC。
对于此类题目,我们可以采用斜率优化 DP 的方式优化。
由于在计算时,\(i\) 是确定的,因此 \(dp_i\) 及 \(S_i\) 均可视为常数。唯二的变量为 \(dp_j\) 和 \(S_j\),这启示我们将其变形成函数的形式,最终可以得到:

\[dp_j + aS_j^2 = (2as_i+b) \cdot S_j + (dp_i - as_i^2 - bs_i - c) \]

参考一次函数的 \(y=kx+b\),我们可以得到

\[y=dp_j + aS_j^2 \]

\[k=2as_i+b \]

\[x=S_j \]

\[b=dp_i-as_i^2-bs_i-c \]

由于我们最终要求的是最大的 \(dp_i\),即求出 \(b\) 最大,因此我们要求的就是使截距最大的 \(j\) 值。
同时,我们也可以据此求出有序实数对 \((S_j, dp_j + S_j^2)\),从而在平面直角坐标系中表示出这些点
image
参考单调队列思想,我们可以找出永远不会作为最大值的所有点,此时,剩余的所有点一定会在这些点的上凸包(最小值为下凸包)上
因此,我们只需要维护这个凸包就可以了,计算的时候,结果即为第一个斜率小于 \(k\) 的线段的左侧点

对于此题,由于 \(x,y\) 的单调性,我们可以维护一个双向队列,每次当队头线段的斜率 \(>k\) 时,就弹出队头;加入该点后不满足凸包性质,就弹出队尾;

代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long LL;

const int N = 1000005;

LL f[N], s[N], g[N], q[N];
int n, a, b, c;

LL x(int u){
    return s[u];
}

LL y(int u){
    return f[u] + a * s[u] * s[u];
}

int main(){
    scanf("%d%d%d%d", &n, &a, &b, &c);
    for (int i = 1; i <= n; i ++ ) scanf("%lld", &g[i]), s[i] = s[i - 1] + g[i];
    
    int hh = 0, tt = 0;

    for (int i = 1; i <= n; i ++ ) {
        while (hh < tt && y(q[hh + 1]) - y(q[hh]) >= (2 * a * s[i] + b) * (x(q[hh + 1]) - x(q[hh]))) hh ++ ;
        int j = q[hh];
        f[i] = f[j] + a * (s[i] - s[j]) * (s[i] - s[j]) + b * (s[i] - s[j]) + c;
        while (hh < tt && (y(q[tt]) - y(q[tt - 1])) * (x(i) - x(q[tt])) <= (y(i) - y(q[tt])) * (x(q[tt]) - x(q[tt - 1]))) tt -- ;
        q[ ++ tt] = i;
    }

    printf("%lld\n", f[n]);

    return 0;

}

蒟蒻犯的若至错误

  • 推式子把 \(aS_j^2\) 的系数推没了(

标签:int,APIO2010,凸包,hh,行动队,luoguP3628,tt,dp,LL
From: https://www.cnblogs.com/XiaoJuRuoUP/p/-/lnsyoj538_luoguP3628

相关文章

  • P3629 [APIO2010] 巡逻
    原题可以发现,当\(K=0\)时,答案为\(2(n-1)\),而当在两端点连了一条边后,则操作方法为如果这条路径上的某条边被标记过,则取消这条边标记;否则把这条边标记为标记过,答案即为未被标记的边*2+标记过的边+连边的个数当\(K=1\)时:答案显然为树的直径当\(K=2\)时:我们还是考......
  • 洛谷P3629 [APIO2010] 巡逻题解
    题目链接P3629[APIO2010]巡逻-洛谷|计算机科学教育新生态(luogu.com.cn)思路n个村庄,n-1条道路,原图为树1.若k=0(不修建道路)那么答案为(n-1)*2 每个道路会走两遍2.若k为1(修建一条道路)设修建的道路(r1)所在的环长度为L那么答案为(n-1)*2-L+2可以看到r1所在环的道路只走了......
  • 【题解】[APIO2010] 信号覆盖
    题目分析:其实就是涉及四个点之间的位置关系,三个点形成圆判断是否包含另一个点。考虑四个点之间形成的多边形只可能是凸四边形或者是凹四边形,如下图所示:(上图为凸多边形)......
  • 洛谷P3628 特别行动队 题解报告
    题目地址题意:把正整数序列分隔为若干区间,若单个区间的元素之和为X,则其贡献为\(aX^2+bX+c\)。求所有区间的贡献之和的最大值。分析:斜率优化dp模板题。这篇博客描述得......
  • [APIO2010] 特别行动队
    Statement传送门Solution先考虑最暴力的\(dp\),也就是\(f_i=\max_{j=0}^if_j+a(s_i-s_j)^2+b(s_i-s_j)+c\),其中\(s_i\)表示\(x_i\)的前缀和.那么此时我们可以把式子拆......
  • [APIO2010]巡逻
    做题时间:2022.10.10\(【题目描述】\)给定一棵\(N(N\leq10^5)\)个点的树,现在可以在这些点之间建立\(k(1\leqk\leq2)\)条边,使得从编号1的点便利一遍所有的边后返回......
  • 做题记录整理图论1 P3629 [APIO2010] 巡逻(2022/10/3)
    P3629[APIO2010]巡逻写一道题顶写三道题系列,为了写这道题专门去学习了树的直径的两种求法,可以说是血赚了https://www.luogu.com.cn/blog/lscsznmhw/solution-p3629......