質問の意味:
Slastyonaはケーキ屋をオープンし、彼女はケーキボックスでは、より高価な販売することができますケーキの種類で満たさ収益性の高い、より箱の中に入れることができました。ケーキの種類装着されたボックスの値の規定に従います。彼女は今日のケーキの上にロードされたk個の箱を聞かせする必要があり、彼女のボックスは空にすることはできません。満たされたケーキは、連続的な範囲から取られなければなりません。Slastyonaは、すべてのケーキの箱の合計値を最大化します。彼女は、可能な最大値を決定するのに役立ちます。
入力フォーマット:最初の行番号及びケーキボックスを表す2つの正の整数nは、k個を含有します。2行目は含まnは正の整数、i番目のカテゴリは、I THケーキを表します
出力フォーマット:ボックスの合計値を表す正の整数。
範囲:保証n∈[1,35000]と整数、k∈[1、分(N、50)]であり、整数です。ケーキ型∈[1、N]の合計数を確認し、整数であることができます。
\(F_ {I、J} \) 前方を表す\(I \)分割の数\(J \)電流の最大値によって生成さを
明確次いでDPの範囲、\(col_ {I、Jは} \)を表し\([I、J] \ ) の異なる種類の数で
だから、明らかにこれはある(O(KN ^ 2)\ \) 、および渡すことができませんでした
我々は、おそらく範囲にケーキを引き起こす可能性があることを考えるの貢献であり、それはその位置+1この範囲の同じ種類である、ツリーラインの最適化の使用を考慮することができ、あなたは、ツリーラインの最適化を使用することができます
この谷はもっと語っている問題にロサンゼルスギャング溶液に行くことができます
// This code Write By chtholly_micromaker(MicroMaker)
#include <cstdio>
#include <cctype>
#include <iostream>
#include <cstring>
#define reg register
using namespace std;
const int MaxN=35005;
const int MaxK=55;
struct Node
{
int val,lazy;
};
template <class t> inline void rd(t &s)
{
s=0;
reg char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
return;
}
int pre[MaxN],pos[MaxN];
int f[MaxK][MaxN];
struct SegTree
{
#define rt (u>>1)
#define lson (u<<1)
#define rson (u<<1|1)
Node tr[MaxN<<2];
inline void clear()
{
memset(tr,0,sizeof tr);
return;
}
inline void pushup(int u)
{
tr[u].val=max(tr[lson].val,tr[rson].val);
return;
}
inline void pushdown(int u,int l,int r)
{
if(tr[u].lazy)
{
tr[lson].lazy+=tr[u].lazy;
tr[rson].lazy+=tr[u].lazy;
tr[lson].val+=tr[u].lazy;
tr[rson].val+=tr[u].lazy;
tr[u].lazy=0;
}
return;
}
inline void buildtr(int u,int l,int r,int x)
{
if(l==r)
{
tr[u].val=f[x][l-1];
return;
}
reg int mid=(l+r)>>1;
buildtr(lson,l,mid,x);
buildtr(rson,mid+1,r,x);
pushup(u);
return;
}
inline void change(int u,int l,int r,int ql,int qr,int x)
{
if(ql<=l&&r<=qr)
{
tr[u].val+=x;
tr[u].lazy+=x;
return;
}
pushdown(u,l,r);
reg int mid=(l+r)>>1;
if(ql<=mid)
change(lson,l,mid,ql,qr,x);
if(mid<qr)
change(rson,mid+1,r,ql,qr,x);
pushup(u);
return;
}
inline int query(int u,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
return tr[u].val;
pushdown(u,l,r);
reg int mid=(l+r)>>1,res=0;
if(ql<=mid)
res=max(res,query(lson,l,mid,ql,qr));
if(mid<qr)
res=max(res,query(rson,mid+1,r,ql,qr));
return res;
}
#undef rt
#undef lson
#undef rson
}segtr;
signed main(void)
{
int n,k;
reg int x;
rd(n);rd(k);
for(int i=1;i<=n;++i)
{
rd(x);
pre[i]=pos[x]+1;
pos[x]=i;
}
for(int i=1;i<=k;++i)
{
segtr.clear();
segtr.buildtr(1,1,n,i-1);
for(int j=1;j<=n;++j)
{
segtr.change(1,1,n,pre[j],j,1);
f[i][j]=segtr.query(1,1,n,1,j);
}
}
printf("%d\n",f[k][n]);
return 0;
}