藉助 dp 公式去優化

題目描述

一天,神犇和 LCR 在玩撲克牌。他們玩的是一種叫作「接竹竿」的遊戲。html

遊戲規則是:一共有 nnn 張牌,每張牌上有一個花色 ccc 和一個點數 vvv,花色不超過 kkk 種。將這些牌依次放入一列牌的末端。若放入以前這列牌中已有與這張牌花色相同的牌,你能夠選擇將這張牌和任意一張花色相同的牌之間的全部牌所有取出隊列(包括這兩張牌自己),並獲得與取出的全部牌點數和相同的分數。如今已知 LCR 把這 nnn 張牌放入隊列的順序,求她最多能得多少分。優化

輸入順序即爲 LCR 放入隊列的順序。即,cic_ici​​ 表示第 iii 張放入的牌的花色,viv_ivi​​ 表示第 iii 張放入的牌的點數。ui

請注意,若是你知道相似的紙牌遊戲,請尤爲仔細地閱讀規則,以避免由於理解題意錯誤而出現沒必要要的問題。spa

輸入格式

第一行兩個整數 n,kn,kn,k。
第二行,nnn 個整數 c1,c2,...,cnc_1,c_2,...,c_nc1​​,c2​​,...,cn​​ 表示花色,知足 1≤ci≤k1\leq c_i\leq k1ci​​k。
第三行,nnn 個整數 v1,v2,...,vnv_1,v_2,...,v_nv1​​,v2​​,...,vn​​ 表示點數。
code

輸出格式

輸出一行一個整數,表示最多能獲得的分數。htm

樣例

樣例輸入 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
blog

樣例輸入 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≤1091\leq n\leq 10^6,1\leq k\leq 10^6,1\leq v_i\leq 10^91n10隊列

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

題意 :相似於「拉火車」遊戲,不過不太同樣的是當出現相同的狀況後你能夠選擇拉或者不拉,ip

思路分析 : 一看就是個 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\n", 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;
}
相關文章
相關標籤/搜索