首页 > 其他分享 >题解:CF704B Ant Man

题解:CF704B Ant Man

时间:2024-10-04 22:01:22浏览次数:7  
标签:Gr int 题解 Ll CF704B Ant 插入 Lr Gl

来的,套路都一样,预设型 DP。

把那个式子拆开,看每个数单独的贡献。

  • 一个数比它左边的数小,它的贡献就是:\(-x_i + b_i\)
  • 比它左边的数大,它的贡献就是:\(x_i + a_i\)
  • 比它右边的数小,它的贡献就是:\(-x_i + d_i\)
  • 比它右边的数大,它的贡献就是:\(x_i + c_i\)

即:

int Gl(int i) { // > 左边
    return x[i] + a[i];
}
int Gr(int i) { // > 右边
    return x[i] + c[i];
}
int Ll(int i) { // < 左边
    return -x[i] + b[i];
}
int Lr(int i) { // < 右边
    return -x[i] + d[i];
}

令 \(f_{i,j}\) 表示已经插入 \(i\) 个数,这些数构成了 \(j\) 个连续段。

新插入的数比后插入的数小,所以一个数插进去的时候可以直接根据前后有没有数来计算贡献。

分类讨论即可,我分的情况比较细致,其实有几个情况有重合,但胜在好理解。

如果 \(i=S\):

  • 插入到最左边,形成单独的块:
    • \(f_{i,j} = f_{i-1,j-1}+Lr(i)\)
  • 插入到最左边块的左边。如果 \(E\) 已经插入,并且 \(j=1\),这种情况就不成立了:
    • \(f_{i,j} = f_{i-1,j}+Gr(i)\)

如果 \(i=E\):

  • 插入到最右边,形成单独的块:
    • \(f_{i,j} = f_{i-1,j-1}+Ll(i)\)
  • 插入到最右边块的右边。如果 \(S\) 已经插入,并且 \(j=1\),这种情况不成立:
    • \(f_{i,j} = f_{i-1,j}+Gl(i)\)

接下来看平常的情况:

  • 插入到所有数最左边,构成一个新块。如果 \(S\) 已经插入则不成立:
    • \(f_{i,j} = f_{i-1,j-1}+Ll(i)+Lr(i)\)
  • 插入到最左边块的左边。如果 \(S\) 已经插入则不成立:
    • \(f_{i,j} = f_{i-1,j}+Ll(i)+Gr(i)\)
  • 插入到所有数最右边,构成一个新块。如果 \(E\) 已经插入则不成立:
    • \(f_{i,j} = f_{i-1,j-1}+Ll(i)+Lr(i)\)
  • 插入到最右边块的右边。如果 \(E\) 已经插入则不成立:
    • \(f_{i,j} = f_{i-1,j}+Gl(i)+Lr(i)\)
  • 插到中间某块的左边。注意一定要有中间块,所以要满足 \(j>1\):
    • \(f_{i,j} = f_{i-1,j}+Ll(i)+Gr(i)\)
  • 插到中间某块的右边。注意一定要有中间块,所以要满足 \(j>1\):
    • \(f_{i,j} = f_{i-1,j}+Gl(i)+Lr(i)\)
  • 插到中间单独成块。两边一定要有块,所以要满足 \(j > 2\):
    • \(f_{i,j} = f_{i-1,j-1}+Ll(i)+Lr(i)\)
  • 插到中间链接两个块:
    • \(f_{i,j} = f_{i-1,j+1}+Gl(i)+Gr(i)\)

对于 DP 边界详细见代码。

代码用一些技巧合并了重复的情况。

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int maxN = 5007;

int n, f[maxN][maxN];
int S, T;

int x[maxN], a[maxN], b[maxN], c[maxN], d[maxN];
int Gl(int i) {
    return x[i] + a[i];
}
int Gr(int i) {
    return x[i] + c[i];
}
int Ll(int i) {
    return -x[i] + b[i];
}
int Lr(int i) {
    return -x[i] + d[i];
}

int chkmin(int &x, int y) {
    return x = x > y ? y : x;
}

signed main() {
    cin >> n >> S >> T;
    for (int i = 1; i <= n; i++) cin >> x[i];
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int i = 1; i <= n; i++) cin >> d[i];

    memset(f, 0x3f, sizeof(f));
    if (S == 1)
        f[1][1] = Lr(1);
    else if (T == 1)
        f[1][1] = Ll(1);
    else
        f[1][1] = Ll(1) + Lr(1);
    for (int i = 2; i < n; i++) {
        for (int j = 1; j <= i; j++) {
            if (i == S || i == T) {
                if (i == S) {
                    chkmin(f[i][j], f[i - 1][j - 1] + Lr(i));
                    if (j > (i > T))
                        chkmin(f[i][j], f[i - 1][j] + Gr(i));
                }
                else {
                    chkmin(f[i][j], f[i - 1][j - 1] + Ll(i));
                    if (j > (i > S))
                        chkmin(f[i][j], f[i - 1][j] + Gl(i));
                }
                continue;
            }
            if (i > S && i > T && j == 1) continue;

            if (j > (i > T) + (i > S))
                chkmin(f[i][j], f[i - 1][j - 1] + Ll(i) + Lr(i));
            chkmin(f[i][j], f[i - 1][j + 1] + Gl(i) + Gr(i));
            if (i < S || j != 1)
                chkmin(f[i][j], f[i - 1][j] + Ll(i) + Gr(i));
            if (i < T || j != 1)
                chkmin(f[i][j], f[i - 1][j] + Gl(i) + Lr(i));
        }
    }
    if (T == n)
        f[n][1] = f[n - 1][1] + Gl(n);
    else if (S == n)
        f[n][1] = f[n - 1][1] + Gr(n);
    else
        f[n][1] = f[n - 1][2] + Gl(n) + Gr(n);

    cout << f[n][1] << '\n';
}

标签:Gr,int,题解,Ll,CF704B,Ant,插入,Lr,Gl
From: https://www.cnblogs.com/ccxswl/p/18447378

相关文章

  • 题解:P8973 『GROI-R1』 继续深潜,为了同一个梦想
    换根dp模板题。\(f_i\)是在以\(i\)为根的子树中,以\(i\)为链的一个端点且\(i\)在点集中的合法点集个数。\(ans_i\)表示包含\(i\)的合法点集个数。当\(x\)为树根时:\[ans_x={f_x\choose2}-\sum_{s\inson}{2f_s+1\choose2}+f_x\]简单解释一下,\({f_x\ch......
  • [题解][洛谷P3584] LAS
    题目描述有n个蛋糕和n个人,每个蛋糕的热量是Ci。第i个人可以选择吃第i或第i+1个蛋糕,第n个人可以选择吃第n或第1个蛋糕。若一个蛋糕被两个人吃,那么每个人得到的热量是Ci/2.若一个人改变自己的选择,得到的热量增加,那么他会不满意。试输出让所有人满意的解,输出每个人吃蛋糕的序号......
  • Centos7 停止维护之后 升级gcc||找不到devtoolset-8-gcc* 问题解决方案
    为了去小米澎湃互联组,感觉必须得拿下linux网络编程,今天第一步这个centos就给我拉了坨大的问题实质SCL源没换,相信你也在别的教程上看到要安装centos-release-scl吧?有坑!安装完成后在/etc/yum.repos.d目录下会出现CentOS-SCLo-scl.repo和CentOS-SCLo-scl-rh.repo两个文件,......
  • [题解][洛谷P1578] 奶牛浴场
    题目描述在长宽为L,W的二维平面上有n个障碍点,试找到一个不覆盖任何障碍点(但点可以在边缘线上的)面积最大的矩形(长宽均与坐标轴平行)。输出面积。题意分析n的范围在5e3,考虑O(n2)的做法。易得面积最大的矩形四条边要么有障碍点,要么覆盖的边界。否则四条边可以继续扩展,面积会变得更......
  • [题解][洛谷P1633] 二进制
    题目描述有三个整数A,B,C,构造三个整数X,Y,Z满足:1.A,B,C在二进制下1的数量分别与X,Y,Z相等;2.X,Y,Z在二进制下的长度不超过A,B,C的最大长度;3.X+Y=Z。输出Z的最小值,若不存在Z,输出-1。题意分析首先考虑X,Y在什么情况下会使1的数量发生改变。设x,y,z分别表示X,Y,Z中1的数量,则......
  • CF542C题解
    传送门:https://codeforces.com/problemset/problem/542/C我们把序列的映射关系看作\(i\rightarrowf(i)\)的边,要使\(f(f(i))=f(i)\),显然存在\(i\)点距离不超过\(1\)的长度为\(1\)的自环。推广到\(f^{(k)}(x)\)满足题意则会在距离\(x\)点距离不超过\(k\)的长度为\(k\)的环。我们......
  • CF242D题解
    传送门:https://codeforces.com/problemset/problem/242/D对于一个点,显然一旦达到额定值后,其他任何操作都无法使他减小,于是我们得出一个贪心性质,当且仅当一个点不合法时,才取增加他的值。同理,我们可以证明,问题必定有解,因为若一个点被选择,必定是因为其曾不合法,选择后使其\(+1\)合法,......
  • CF549B题解
    传送门:https://codeforces.com/problemset/problem/549/B和CF242C思路完全相同,对于一个点,显然一旦达到额定值后,其他任何操作都无法使他减小,于是我们得出一个贪心性质,当且仅当一个点不合法时,才取增加他的值。同理,我们可以证明,问题必定有解,因为若一个点被选择,必定是因为其曾不合法,......
  • [题解]P7077 [CSP-S2020] 函数调用
    P7077[CSP-S2020]函数调用题意简述给定一个长度为\(n\)的序列\(a_1,a_2,\dots,a_n\),给定\(m\)个函数,每个函数可能是下面\(3\)种类型,用\(T_x\)表示函数\(x\)的类型:\(T_x=1\),对下标\(p\)增加\(v\)。\(T_x=2\),对所有元素乘\(v\)。\(T_x=3\),由若干类型\(1\)和类型\(2\)组成......
  • 【题解】B - 三元上升子序列
    目录题目内容DescriptionInputOutput数据规模与约定思路代码题目内容DescriptionErwin最近对一种叫thair的东西巨感兴趣。。。在含有\(n\)个整数的序列\(a_1,a_2,\ldots,a_n\)中,三个数被称作thair当且仅当\(i\ltj\ltk\)且\(a_i\lta_j\lta_k\)。求一个序列中thair......