The Bakery CodeForces - 834D

点击打开链接

状态转移方程: dp[i][j]=max(dp[i-1][k]+sum[j]-sum[k]) 复杂度为k*n*n

但是求最大值这个过程可以用线段树来优化

要查询一个区间有多少种颜色 先处理处每个位置i的左边最近的同色位置在哪 记为left[i] 然后对[left[i]+1,i]这个区间加一 因为再靠左的区间已经有另一个同色发挥作用了 没必要再更新

#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f

struct node
{
    int l;
    int r;
    int val;
    int laz;
};

node tree[140010];
int dp[100][35010];
int clr[35010],lef[35010],book[35010],pre[35010];
int n,k;

void pushup(int cur)
{
    tree[cur].val=max(tree[2*cur].val,tree[2*cur+1].val);
    return;
}

void pushdown(int cur)
{
    if(tree[cur].laz!=0)
    {
        tree[2*cur].val+=tree[cur].laz;
        tree[2*cur].laz+=tree[cur].laz;
        tree[2*cur+1].val+=tree[cur].laz;
        tree[2*cur+1].laz+=tree[cur].laz;
        tree[cur].laz=0;
    }
    return;
}

void build(int l,int r,int cur)
{
    int m;
    tree[cur].l=l;
    tree[cur].r=r;
    tree[cur].val=0;
    tree[cur].laz=0;
    if(l==r)
    {
        tree[cur].val=pre[l];
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    pushup(cur);
    return;
}

void update(int pl,int pr,int cur)
{
    if(pl<=tree[cur].l&&tree[cur].r<=pr)
    {
        tree[cur].val++;
        tree[cur].laz++;
        return;
    }
    pushdown(cur);
    if(pl<=tree[2*cur].r) update(pl,pr,2*cur);
    if(pr>=tree[2*cur+1].l) update(pl,pr,2*cur+1);
    pushup(cur);
    return;
}

int query(int pl,int pr,int cur)
{
    int res;
    if(pl<=tree[cur].l&&tree[cur].r<=pr)
    {
        return tree[cur].val;
    }
    pushdown(cur);
    res=-N;
    if(pl<=tree[2*cur].r) res=max(res,query(pl,pr,2*cur));
    if(pr>=tree[2*cur+1].l) res=max(res,query(pl,pr,2*cur+1));
    return res;
}

int main()
{
    int i,j;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&clr[i]);
        lef[i]=book[clr[i]]+1,book[clr[i]]=i;
    }
    for(j=1;j<=n;j++)
    {
        dp[1][j]=dp[1][j-1];
        if(lef[j]==1) dp[1][j]++;
    }
    for(i=2;i<=k;i++)
    {
        for(j=1;j<=n;j++)
        {
            pre[j]=dp[i-1][j-1];
        }
        build(1,n,1);
        for(j=1;j<=n;j++)
        {
            update(lef[j],j,1);
            dp[i][j]=query(1,j,1);
        }
    }
    printf("%d\n",dp[k][n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/80579615