zoukankan      html  css  js  c++  java
  • 【题解】CF#1012 C-Hill

      感觉这题的状态还是比较明显的。设置状态 (f[i][j][0/1]) 表示dp到第 (i) 个位置,前面(包括这里)已经出现了 (j) 个山峰,当前位置是不是山峰即可 dp。这样的状态有一个很优秀的性质:我们注意到在最后的答案当中,我们一定不会去修改山峰的高度(这样做显然毫无意义)。那么这样dp我们可以通过分类讨论直接计算出使一个节点成为山峰的代价。

      如:降低一个位置使得前面与后面均为山峰,降低到小于两者的高度。降低一个位置使得后一个位置为山峰,降低一个位置使得前一个位置为山峰,都只要降低到为山峰的位置更低即可。复杂度很高,但codeforces经常都是玄学复杂度……( • ̀ω•́ )✧

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 100000
    #define int long long
    #define INF 999999999999LL
    int n, K, a[maxn], f[3][maxn][2];
    
    int read()
    {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    int Check(int x, int y, int z) { int t = min(y, z); return x >= t ? x - t + 1 : 0; }
    void Down(int &x, int y) { x = x < y ? x : y; }
    
    signed main()
    {
        n = read(), K = (n >> 1) + 1; if(!(n & 1)) K -= 1; 
        for(int i = 1; i <= n; i ++) a[i] = read();
        int fore = 0, pre = 1, now = 2;
        for(int i = 0; i <= 2; i ++)
            for(int j = 0; j < maxn; j ++)
                f[i][j][0] = f[i][j][1] = INF;
        f[fore][0][0] = f[pre][0][0] = 0; 
        for(int i = 1; i <= n; i ++)
        {
            int t = (i >> 1) + 1;
            for(int j = 0; j < maxn; j ++)
                f[now][j][0] = f[now][j][1] = INF;
            for(int j = 0; j <= i; j ++)
            {
                int t1, t2, t3;
                if(i > 2) t1 = a[i - 2], t2 = a[i - 1], t3 = a[i];
                else if(i > 1) t1 = -INF, t2 = a[i - 1], t3 = a[i];
                else t1 = -INF, t2 = -INF, t3 = a[i];
                Down(f[now][j][1], f[fore][j - 1][1] + Check(t2, t1, t3));
                Down(f[now][j][1], f[fore][j - 1][0] + Check(t2, t3, INF));
                Down(f[now][j][0], f[pre][j][1] + Check(t3, t2, INF));
                Down(f[now][j][0], f[pre][j][0]);
            }
            int tem = fore; fore = pre, pre = now, now = tem;
        }
        for(int i = 1; i <= K; i ++) 
            printf("%I64d ", min(f[pre][i][0], f[pre][i][1]));
        puts("");
        return 0;
    }
  • 相关阅读:
    利用mybatis-generator自动生成代码
    gradle安装
    有关﹤![CDATA[ ]]> 说明
    mysql时间字段转换为毫秒格式
    string 与BigDecimal互转
    VLOOKUP多条件查找不使用辅助列
    BIEE-CSS样式大全
    VBA【遍历每个工作表并将工作表表名赋予B2单元格】
    深入理解公式{1,0}的用法
    DB2解锁
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9753653.html
Copyright © 2011-2022 走看看