Codeforces 834D The Bakery(dp+线段树)

来源:互联网 发布:北京编程培训机构排名 编辑:程序博客网 时间:2024/04/27 15:02

原题链接

Problem Description

Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredients and a wonder-oven which can bake several types of cakes, and opened the bakery.

Soon the expenses started to overcome the income, so Slastyona decided to study the sweets market. She learned it’s profitable to pack cakes in boxes, and that the more distinct cake types a box contains (let’s denote this number as the value of the box), the higher price it has.

She needs to change the production technology! The problem is that the oven chooses the cake types on its own and Slastyona can’t affect it. However, she knows the types and order of n cakes the oven is going to bake today. Slastyona has to pack exactly k boxes with cakes today, and she has to put in each box several (at least one) cakes the oven produced one right after another (in other words, she has to put in a box a continuous segment of cakes).

Slastyona wants to maximize the total value of all boxes with cakes. Help her determine this maximum possible total value.

Input

The first line contains two integers n and k (1 ≤ n ≤ 35000, 1 ≤ k ≤ min(n, 50)) – the number of cakes and the number of boxes, respectively.
The second line contains n integers a1, a2, …, an (1 ≤ ai ≤ n) – the types of cakes in the order the oven bakes them.

Output

Print the only integer – the maximum total value of all boxes with cakes.

Sample Input

4 1
1 2 2 1
7 2
1 3 3 1 4 4 4
8 3
7 7 8 7 7 8 1 7

Sample Output

2
5
6

题目大意

有n块蛋糕,k个盒子,现要设计一种分配方法,使得每个盒子中的不同种类蛋糕数的总和最大,其中一个盒子只能装相邻的一段区间的蛋糕。

解题思路

比赛的时候就想到这题应该是dp的思路,但是后续的内容还是没什么思路,看了官方题解以后才知道可以用线段树来维护这个dp数组,利用它的求区间极值和区间修改功能来解题。dp[i][j]表示前i个蛋糕放在j个盒子中可以达到的总和最大值,那么dp[k][n]就是所需要的答案。详情可见官方题解。

AC代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<algorithm>#include<cmath>#include<vector>#include<string>#include<queue>#include<list>#include<stack>#include<set>#include<map>#define ll long long#define ull unsigned long long#define rep(i,n) for(int i = 0;i < n; i++)#define fil(a,b) memset((a),(b),sizeof(a))#define cl(a) fil(a,0)#define pb push_back#define mp make_pair#define exp 2.7182818#define PI 3.141592653589793#define inf 0x3f3f3f3f#define fi first#define se second#define eps 1e-8#define MOD 1000000007ll#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0)))using namespace std;int y11,y2,op,n,k,v;const int maxnode=150000;struct SegmentTree{    int sumv[maxnode];    int minv[maxnode];    int maxv[maxnode];    int addv[maxnode];    int setv[maxnode];    void maintain(int o,int L,int R)    {        int lson=o<<1;        int rson=o<<1|1;        if(R>L)        {            sumv[o]=sumv[lson]+sumv[rson];            maxv[o]=max(maxv[lson],maxv[rson]);            minv[o]=min(minv[lson],minv[rson]);        }        if(setv[o]>=0)        {            minv[o]=maxv[o]=setv[o];            sumv[o]=setv[o]*(R-L+1);        }        if(addv[o])        {            minv[o]+=addv[o];            maxv[o]+=addv[o];            sumv[o]+=addv[o]*(R-L+1);        }    }    void pushdown(int o)    {        int lson=o<<1;        int rson=o<<1|1;        if(setv[o]>=0)        {            setv[lson]=setv[rson]=setv[o];            addv[lson]=addv[rson]=0;            setv[o]=-1;        }        if(addv[o])        {            addv[lson]+=addv[o];            addv[rson]+=addv[o];            addv[o]=0;        }    }    void update(int o,int L,int R)    {        int lson=o<<1;        int rson=o<<1|1;        if(y11<=L&&y2>=R)        {            if(op==1)            {                addv[o]+=v;            }            else            {                setv[o]=v;                addv[o]=0;            }        }        else        {            pushdown(o);            int m=L+R>>1;            if(y11<=m) update(lson,L,m);            else maintain(lson,L,m);            if(y2>m) update(rson,m+1,R);            else maintain(rson,m+1,R);        }        maintain(o,L,R);    }    void query(int o,int L,int R,int& ssum,int& smin,int& smax)    {        int lson=o<<1;        int rson=o<<1|1;        maintain(o,L,R);        if(y11<=L&&y2>=R)        {            ssum=sumv[o];            smin=minv[o];            smax=maxv[o];        }        else        {            pushdown(o);            int m=L+R>>1;            int lsum=0,lmin=inf,lmax=-inf;            int rsum=0,rmin=inf,rmax=-inf;            if(y11<=m)            {                query(lson,L,m,lsum,lmin,lmax);            }            else maintain(lson,L,m);            if(y2>m)            {                query(rson,m+1,R,rsum,rmin,rmax);            }            else maintain(rson,m+1,R);            ssum=lsum+rsum;            smin=min(lmin,rmin);            smax=max(lmax,rmax);        }    }};SegmentTree t;int dp[60][35111];int a[35111];int prec[35111];int main(void){    scanf("%d%d",&n,&k);    for(int i=1;i<=n;++i)    {        scanf("%d",&a[i]);    }    for(int i=1;i<=k;++i)    {        op=2;v=0;y11=1;y2=n;        t.update(1,1,n);        cl(prec);        for(int j=1;j<=n;++j)        {            op=2;v=dp[i-1][j-1];y11=y2=j;            t.update(1,1,n);        }        for(int j=1;j<=n;++j)        {            op=1;v=1;y11=prec[a[j]]+1;y2=j;            t.update(1,1,n);            int ssum,smin,smax;            op=3;y11=1;y2=j;            t.query(1,1,n,ssum,smin,smax);            dp[i][j]=smax;            prec[a[j]]=j;        }    }    printf("%d\n",dp[k][n]);    return 0;}
原创粉丝点击