Codeforces 833B 线段树优化 dp

Posted 掉血菜鸡煮熟中

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 833B 线段树优化 dp相关的知识,希望对你有一定的参考价值。

Codeforces  833B  The Bakery

题意: n 个数要分成 k 块,每块的价值是其不同数的个数,问价值和最大是多少。

tags: dp[i][j]表示前 j 个数分成 i 块的最大权值和,转移: dp[i][j] = max( dp[i-1][k] + val[k+1][j] ) , k是 1~j 。 但这个过程其实并不好转移,要利用累加的特点,用线段树进行优化 (感觉我不看题解是想不到的,2333)

大概就是,对于第 i 层,我们假定已经知道了第 i-1 层,也就是求出了 dp[i-1][j],现在要求dp[i][j]。遍历 j 从 1~n ,对于第 j 个数,假定 a[j] 上一个位置是 last[j],那我们对 last[j]+1 ~ j  位置都累加一个 1 。这样的话,dp[i-1][k] 就变成了 dp[i][j] ,然后求个区间最值就行了。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 35005, M = 55;

int n, k, a[N], last[N], pre[N];
ll  tr[N<<2], dp[M][N], lazy[N<<2];
void pushdown(int ro, int l, int r)
{
    if(l==r) return ;
    if(lazy[ro])
    {
        lazy[ro<<1] += lazy[ro];
        lazy[ro<<1|1] += lazy[ro];
        tr[ro<<1] += lazy[ro];
        tr[ro<<1|1] += lazy[ro];
        lazy[ro] = 0;
    }
}
void update(int ql, int qr, int ro, int l, int r, int c)
{
    if(ql<=l && r<=qr) {
        lazy[ro]+=c, tr[ro]+=c;
        return ;
    }
    pushdown(ro, l, r);
    int mid = l+r>>1;
    if(ql<=mid) update(ql, qr, ro<<1, l, mid, c);
    if(mid<qr) update(ql, qr, ro<<1|1, mid+1, r, c);
    tr[ro] = max(tr[ro<<1], tr[ro<<1|1]);
}
ll  query(int ql, int qr, int ro, int l, int r)
{
    if(ql<=l && r<=qr)  return tr[ro];
    pushdown(ro, l, r);
    ll  ans = 0;
    int mid = l+r>>1;
    if(ql<=mid) ans = max(ans, query(ql, qr, ro<<1, l, mid));
    if(mid<qr) ans = max(ans, query(ql, qr, ro<<1|1, mid+1, r));
    return ans;
}
void build(int ro, int l, int r, int i)
{
    lazy[ro] = 0, tr[ro] = 0;
    if(l==r) {
        tr[ro] = dp[i][l-1];
        return ;
    }
    int mid = l+r>>1;
    build(ro<<1, l, mid, i);
    build(ro<<1|1, mid+1, r, i);
    tr[ro] = max(tr[ro<<1], tr[ro<<1|1]);
}
int main()
{
    scanf("%d %d", &n, &k);
    rep(i,1,n) {
        scanf("%d", &a[i]);
        last[i] = pre[a[i]],  pre[a[i]] = i;
    }
    rep(i,1,k)
    {
        build(1, 1, n, i-1);
        rep(j,1,n)
        {
            update(last[j]+1, j, 1, 1, n, 1);
            dp[i][j] = query(1, j, 1, 1, n);
        }
    }
    printf("%lld\n", dp[k][n]);

    return 0;
}

以上是关于Codeforces 833B 线段树优化 dp的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces - 833B The Bakery

学术篇CF833B TheBakery 分治dp+主席树

CF833B The Bakery

Codeforces 786B - Legacy(线段树优化建图)

Codeforces 1045A Last chance 网络流,线段树,线段树优化建图

codeforces786B Legacy 线段树优化建图