• 借助 dp 公式去优化


    题目描述

    一天,神犇和 LCR 在玩扑克牌。他们玩的是一种叫做“接竹竿”的游戏。

    游戏规则是:一共有 nnn 张牌,每张牌上有一个花色 ccc 和一个点数 vvv,花色不超过 kkk 种。将这些牌依次放入一列牌的末端。若放入之前这列牌中已有与这张牌花色相同的牌,你可以选择将这张牌和任意一张花色相同的牌之间的所有牌全部取出队列(包括这两张牌本身),并得到与取出的所有牌点数和相同的分数。现在已知 LCR 把这 nnn 张牌放入队列的顺序,求她最多能得多少分。

    输入顺序即为 LCR 放入队列的顺序。即,cic_ici​​ 表示第 iii 张放入的牌的花色,viv_ivi​​ 表示第 iii 张放入的牌的点数。

    请注意,如果你知道类似的纸牌游戏,请尤其仔细地阅读规则,以免因为理解题意错误而出现不必要的问题。

    输入格式

    第一行两个整数 n,kn,kn,k。
    第二行,nnn 个整数 c1,c2,...,cnc_1,c_2,...,c_nc1​​,c2​​,...,cn​​ 表示花色,满足 1≤ci≤k1leq c_ileq k1ci​​k。
    第三行,nnn 个整数 v1,v2,...,vnv_1,v_2,...,v_nv1​​,v2​​,...,vn​​ 表示点数。

    输出格式

    输出一行一个整数,表示最多能得到的分数。

    样例

    样例输入 1

    7 3
    1 2 1 2 3 2 3
    1 2 1 2 3 2 3

    样例输出 1

    13

    样例解释 1

    第 1 步,向队列加入 111。现在的队列:111
    第 2 步,向队列加入 222。现在的队列:1,21,21,2
    第 3 步,向队列加入 111。现在的队列:1,2,11,2,11,2,1
    第 4 步,向队列加入 222,取出 2,1,22,1,22,1,2。现在的队列:111
    第 5 步,向队列加入 333。现在的队列:1,31,31,3
    第 6 步,向队列加入 222。现在的队列:1,3,21,3,21,3,2
    第 7 步,向队列加入 333,取出 3,2,33,2,33,2,3。现在的队列:111

    样例输入 2

    18 5
    5 2 3 5 1 3 5 2 1 4 2 4 5 4 1 1 1 5
    8 2 7 6 10 8 10 9 10 2 4 7 7 7 7 9 7 3

    样例输出 2

    123

    数据范围与提示

    对于 100%100\%100% 的数据,1≤n≤106,1≤k≤106,1≤vi≤1091leq nleq 10^6,1leq kleq 10^6,1leq v_ileq 10^91n10

    6​​,1k106​​,1vi​​109​​。

    题意 :类似于“拉火车”游戏,不过不太一样的是当出现相同的情况后你可以选择拉或者不拉,

    思路分析 : 一看就是个 dp ,

          dp[i] = dp[i-1]

          dp[i] = max(dp[i], dp[j-1]+sum[i]-sum[j-1]) , i 与 j 为花色相同的地方

          第一次写的时候就类似纯暴力的了,每次转移的时候从前面所有相同的地方转移,用 vector 存的,超时.... 后面发现 转移方程中的式子是可以优化的,每次找 dp[j-1]-sum[j-1]中最大的转移即可

    代码示例 :

    #define ll long long
    const ll maxn = 1e6+5;
    
    ll n, k;
    ll c[maxn], v[maxn];
    ll sum[maxn], dp[maxn];
    ll color[maxn];
    
    void solve() {
        memset(color, 0x8f, sizeof(color)); 
        for(ll i = 1; i <= n; i++){
            dp[i] = dp[i-1];
            dp[i] = max(dp[i], sum[i]+color[c[i]]);
            color[c[i]] = max(color[c[i]], dp[i-1]-sum[i-1]); 
        }
        printf("%lld
    ", dp[n]);
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        
        cin >> n >> k;
        for(ll i = 1; i <= n; i++) {
            scanf("%lld", &c[i]);
        } 
        for(ll i = 1; i <= n; i++) {
            scanf("%lld", &v[i]);
            sum[i] = sum[i-1]+v[i];
        }
        
        solve();
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    oracle 10g正则表达式REGEXP_LIKE用法
    impdp时出现ORA-39125错误的解决方法
    使用rman恢复备份集到不同的主机上
    ORA-01110: data file 1: '/opt/ora10g/oradata/orcla/system01.dbf'错误
    Oracle模拟文件损坏BBED
    RMAN进行基于数据块的恢复
    转:Java中Image的水平翻转、缩放与自由旋转操作
    hue耗流量优化
    解决hue/hiveserver2对于hive date类型显示为NULL的问题
    解决kylin sync table报错:MetaException(message:java.lang.ClassNotFoundException Class org.apache.hive.hcatalog.data.JsonSerDe not found
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9673072.html
Copyright © 2020-2023  润新知