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

834D - The Bakery

思路:dp[i][j]表示到第j个数为止分成i段的最大总和值。

dp[i][j]=max{dp[i-1][x]+c(x+1,j)(i-1≤x≤j-1)},c(x+1,j)表示x+1到j的不同的值。

用线段树维护一下最大值。

上图最后一个点取不到,不解释,不明白请评论。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls rt<<1,l,m
#define rs rt<<1|1,m+1,r
#define pb push_back 
const int INF=0x3f3f3f3f;
const int N=35555;
int tree[4*N],lazy[4*N];
int dp[55][N];
int now[N],pre[N],a[N];
int i;

void push_up(int rt)
{
    tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}

void push_down(int rt)
{
    tree[rt<<1]+=lazy[rt];
    lazy[rt<<1]+=lazy[rt];
    tree[rt<<1|1]+=lazy[rt];
    lazy[rt<<1|1]+=lazy[rt];
    lazy[rt]=0;
}

void build(int rt,int l,int r)
{
    if(l==r)
    {
        tree[rt]=dp[i-1][l];
        return ;
    }
    int m=(l+r)>>1;
    build(ls);
    build(rs);
    push_up(rt);
}

void update(int p,int delta,int rt,int l,int r)
{
    if(l==r)
    {
        tree[rt]+=delta;
        return ;
    }
    int m=(l+r)>>1;
    if(p<=m)update(p,delta,ls);
    else update(p,delta,rs);
    push_up(rt);
}

void Update(int L,int R,int delta,int rt,int l,int r)
{
    if(L<=l&&r<=R)
    {
        tree[rt]+=delta;
        lazy[rt]+=delta;
        return ;
    }
    if(lazy[rt])push_down(rt);
    int m=(l+r)>>1;
    if(L<=m)Update(L,R,delta,ls);
    if(R>m)Update(L,R,delta,rs);
    push_up(rt);
}

int query(int L,int R,int rt,int l,int r)
{
    if(L<=l&&r<=R)return tree[rt];
    if(lazy[rt])push_down(rt);
    int m=(l+r)>>1,ans=0;
    if(L<=m)ans=max(ans,query(L,R,ls));
    if(R>m)ans=max(ans,query(L,R,rs));
    return ans; 
}

int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        memset(now,0,sizeof(now));
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            pre[i]=now[a[i]];
            now[a[i]]=i;
        }
        dp[1][1]=1;
        for(i=1;i<=k;i++)
        {
            memset(tree,0,sizeof(tree));
            memset(lazy,0,sizeof(lazy));
            build(1,0,n);
            for(int j=i;j<=n;j++)
            {
                Update(pre[j],j-1,1,1,0,n);
                dp[i][j]=query(i-1,j-1,1,0,n);
            }
        }
        cout<<dp[k][n]<<endl;
    }
    return 0;
}

 

posted @ 2017-08-02 18:16  Wisdom+.+  阅读(289)  评论(0编辑  收藏  举报