《CF833B The Bakery》

题目描述

不久前,Slastyona the Sweetmaid 决定开设自己的面包店!她买齐了所需的原料,还有一台可以烘焙多种蛋糕的奇妙烤箱,并开张了面包店。

很快,开支开始超过收入,于是 Slastyona 决定研究甜点市场。她了解到,将蛋糕装入盒子会更有利可图,而且每个盒子里不同种类蛋糕越多(我们将这个数量称为盒子的价值),价格就越高。

她需要改变生产技术!问题在于,烤箱会自行决定蛋糕的种类,Slastyona 无法干预。然而,她知道今天烤箱将要依次烘烤出 n 个蛋糕的类型和顺序。今天,Slastyona 必须准确地用 k 个盒子来打包这些蛋糕,并且每个盒子内必须放入若干(至少一个)连续烘焙出来的蛋糕(换句话说,每个盒子包含一段蛋糕的连续区间)。

Slastyona 希望最大化所有盒子的总价值。请你帮她求出所有盒子的最大可能总价值。

输入格式

第一行包含两个整数 n 和 k(1≤n≤35000,1≤k≤min(n,50))------蛋糕的数量以及盒子的数量。

第二行包含 n 个整数 a1​,a2​,...,an​(1≤ai​≤n)------按照烤箱生产顺序排列的蛋糕类型。

输出格式

输出唯一一个整数,表示所有盒子中的蛋糕最大可能的总价值。

显示翻译

题意翻译

输入输出样例

输入 #1复制

复制代码
4 1
1 2 2 1

输出 #1复制

复制代码
2

输入 #2复制

复制代码
7 2
1 3 3 1 4 4 4

输出 #2复制

复制代码
5

输入 #3复制

复制代码
8 3
7 7 8 7 7 8 1 7

输出 #3复制

复制代码
6

说明/提示

在第一个样例中,Slastyona 只有一个盒子。她必须把所有蛋糕都放进这个盒子里,因此这个盒子有两种类型,价值为 2。

在第二个样例中,最优策略是将前两个蛋糕放入第一个盒子,其余的都放进第二个盒子。则第一个盒子有两种类型,第二个盒子有三种类型,因此总价值为 5。

由 ChatGPT 5 翻译

代码实现;

cpp 复制代码
#include<bits/stdc++.h>
#define re register
#define il inline
using namespace std;

const int N=35005;
const int M=55;

int n,k;
int a[N];
int dp[N][M];
int pre[N], pos[N];
int vis[N], p[N];

struct SegTree{
    struct nd{
        int l,r,v,ad;
    }t[4*N];
    
    void pd(int p){
        if(t[p].ad){
            int lc=p<<1, rc=p<<1|1;
            t[lc].v += t[p].ad;
            t[rc].v += t[p].ad;
            t[lc].ad += t[p].ad;
            t[rc].ad += t[p].ad;
            t[p].ad = 0;
        }
    }
    
    void clr(int i, int p, int l, int r){
        t[p].l=l, t[p].r=r;
        if(l==r){
            t[p].v = dp[l][i];
            return ;
        }
        int m=(l+r)>>1;
        clr(i, p<<1, l, m);
        clr(i, p<<1|1, m+1, r);
        t[p].v = max(t[p<<1].v, t[p<<1|1].v);
    }
    
    void upd(int p, int l, int r, int x){
        if(t[p].l>=l && t[p].r<=r){
            t[p].ad += x;
            t[p].v += x;
            return ;
        }
        pd(p);
        int m=(t[p].l + t[p].r)>>1;
        if(l<=m) upd(p<<1, l, r, x);
        if(r>m) upd(p<<1|1, l, r, x);
        t[p].v = max(t[p<<1].v, t[p<<1|1].v);
    }
    
    int qry(int p, int l, int r){
        if(t[p].l>=l && t[p].r<=r) return t[p].v;
        pd(p);
        int m=(t[p].l + t[p].r)>>1, res=0;
        if(l<=m) res = qry(p<<1, l, r);
        if(r>m) res = max(res, qry(p<<1|1, l, r));
        return res;
    }
}tr[M];

int main(){
    scanf("%d %d", &n, &k);
    for(int i=1;i<=n;i++){
        scanf("%d", &a[i]);
        pre[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    
    for(int i=1;i<=n;i++){
        dp[i][1] = dp[i-1][1];
        if(!vis[a[i]]){
            vis[a[i]] = 1;
            dp[i][1]++;
        }
    }
    
    for(int j=2;j<=k;j++){
        tr[j-1].clr(j-1, 1, 0, n);
        for(int i=1;i<=n;i++){
            tr[j-1].upd(1, pre[i], i-1, 1);
            dp[i][j] = tr[j-1].qry(1, 0, i-1);
        }
    }
    
    printf("%d", dp[n][k]);
    return 0;
}
相关推荐
忘梓.3 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(10)
c++·算法·动态规划·代理模式
foolish..3 小时前
动态规划笔记
笔记·算法·动态规划
消失的dk3 小时前
算法---动态规划
算法·动态规划
羑悻的小杀马特3 小时前
【动态规划篇】欣赏概率论与镜像法融合下,别出心裁探索解答括号序列问题
c++·算法·蓝桥杯·动态规划·镜像·洛谷·空隙法
绍兴贝贝3 小时前
代码随想录算法训练营第四十六天|LC647.回文子串|LC516.最长回文子序列|动态规划总结
数据结构·人工智能·python·算法·动态规划·力扣
愚润求学3 小时前
【动态规划】二维的背包问题、似包非包、卡特兰数
c++·算法·leetcode·动态规划
叫我一声阿雷吧3 小时前
【信奥赛基础】动态规划:小学生也能懂的必考算法入门
算法·动态规划
_F_y13 小时前
背包问题动态规划
算法·动态规划
_F_y14 小时前
两个数组的动态规划
算法·动态规划