codeforces #426 div2(The Bakery)834d
阿新 • • 發佈:2019-02-12
題目連結
本菜感覺這個題目真是難,看了好久的題解才懂起,大致題意就是給一個數組,把陣列連續的分為k部分,每一部分的值等於這部分不同的數字的個數,要讓所有的值加起來最大,問怎樣分。
首先我們來看一下dp:
首先把線段樹用 x<=n)]
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
using namespace std;
#define LL long long
const int N = 35005;
struct TreeNode{
int ma;
int cnt;
}tree[N<<2];
int n;
void PushUp(int now){
tree[now].ma = max(tree[now<<1 ].ma,tree[now<<1|1].ma);
}
void PushDown(int now){
if(tree[now].cnt!=0)
{
int lson = now<<1;
int rson = now<<1|1;
tree[lson].cnt += tree[now].cnt;
tree[lson].ma += tree[now].cnt;
tree[rson].cnt += tree[now].cnt;
tree[rson].ma += tree[now].cnt;
tree[now].cnt = 0;
}
}
void Update(int ul,int ur,int add,int l,int r,int now)
{
if(ul<=l && r <= ur)
{
tree[now].cnt += add;
tree[now].ma += add;
return;
}
PushDown(now);
int mid = (l+r)/2;
if(ul<=mid)
Update(ul,ur,add,l,mid,now<<1);
if(ur>mid)
Update(ul,ur,add,mid+1,r,now<<1|1);
PushUp(now);
}
int Query(int ql,int qr,int l,int r,int now)
{
if(ql <= l && r <= qr)
{
return tree[now].ma;
}
PushDown(now);
int mid = (l+r)/2;
int a1,a2;
a1 = a2 = -9999999;
if(ql<=mid)
{
a1 = Query(ql,qr,l,mid,now<<1);
}
if(qr>mid)
{
a2 = Query(ql,qr,mid+1,r,now<<1|1);
}
return max(a2,a1);
}
int dat[35005];
int dp[35005][55];
int last[35005];
int now[35005];
int main()
{
int k;
while(scanf("%d%d",&n,&k)!=EOF)
{
clr(last);
clr(now);
for(int i = 1;i<=n;i++)
{
scanf("%d",&dat[i]);
last[i] = now[dat[i]];
now[dat[i]] = i;
}
clr(dp);
clr(tree);
for(int i = 1;i<=k;i++)
{
clr(tree);
for(int j = 1;j<=n;j++)
{
Update(j,j,dp[j][i-1],0,n,1);
}
for(int j = i;j<=n;j++)
{
Update(max(last[j],i-1),j-1,1,0,n,1);
/* if(i==3)
{
for(int ii = 1;ii<=n;ii++)
{
cout << Query(ii,ii,0,n,1) << " ";
}
cout << endl;
}*/
//if(i==3 && j)cout << j<<"kk" << Query(2,7,0,n,1) << endl;
dp[j][i] = Query(i-1,j-1,0,n,1);
}
}
printf("%d\n",dp[n][k]);
}
return 0;
}