• CodeForces833 B. The Bakery 线段树维护dp


    题目链接:https://vjudge.net/problem/CodeForces-833B


    题意:
    给长度为n的数组a,和一个整数k
    要求把数组分成连续的k段,每段的权值是该段中不同数的个数,
    输出最大权值和。
    数据范围:n<=35000,k<=min(n,50),1<=a(i)<=n

    题解:
    很容易想到暴力dp的方式
    dp[i][j]:前1-i个数分成了j个段
    那么dp[i][j]=max(dp[k][j-1]+val[k+1][i]) //val[i][j]表示区间i-j中不同数的个数
    这个方法的复杂度就是O(n^2*k),很显然不可行

    那么我们可以把找max(dp[k][j-1]+val[k+1][i])这个过程使用线段树优化掉
    我们可以从1-n的数分成j段建立一颗线段树,也就是对dp[x][j](1<=x<=n)建一颗线段树维护这n个数的最大值
    然后对dp[i][j]的求解可以从维护dp[x][j-1]这一颗树中查找区间【1,(i-1)】的最大值

    但是有一点不对,因为dp[i][j]由dp[k][j-1]和val[k+1][i]两部分构成,所以只有dp[k][j-1]最大并不一定可以得到
    dp[i][j]最大,所以我们就要想办法处理一下维护dp[x][j]的线段树,让线段树维护这两部分的和

    对于下面的一组数(下标从1开始)
    7 8 1 7
    第二个7的有效区域是[2,4],那么我们可以在原有维护dp[x][j]的线段树基础上,线段树在[2,4]这个区间的值都加1
    这样的话就相当于让线段树维护了两部分的和

    
    
    /*
    题意:
    给长度为n的数组a,和一个整数k
    要求把数组分成连续的k段,每段的权值是该段中不同数的个数,
    输出最大权值和。
    数据范围:n<=35000,k<=min(n,50),1<=a(i)<=n
    
    题解:
    很容易想到暴力dp的方式
    dp[i][j]:前1-i个数分成了j个段
    那么dp[i][j]=max(dp[k][j-1]+val[k+1][i]) //val[i][j]表示区间i-j中不同数的个数
    这个方法的复杂度就是O(n^2*k),很显然不可行
    
    那么我们可以把找max(dp[k][j-1]+val[k+1][i])这个过程使用线段树优化掉
    我们可以从1-n的数分成j段建立一颗线段树,也就是对dp[x][j](1<=x<=n)建一颗线段树维护这n个数的最大值
    然后对dp[i][j]的求解可以从维护dp[x][j-1]这一颗树中查找区间【1,(i-1)】的最大值
    
    但是有一点不对,因为dp[i][j]由dp[k][j-1]和val[k+1][i]两部分构成,所以只有dp[k][j-1]最大并不一定可以得到
    dp[i][j]最大,所以我们就要想办法处理一下维护dp[x][j]的线段树,让线段树维护这两部分的和
    
    对于下面的一组数(下标从1开始)
    7 8 1 7
    第二个7的有效区域是[2,4],那么我们可以在原有维护dp[x][j]的线段树基础上,线段树在[2,4]这个区间的值都加1
    这样的话就相当于让线段树维护了两部分的和
    
    */
    
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include<algorithm>
    #include <queue>
    #include <map>
    using namespace std;
    typedef long long ll;
    const int maxn=5e4+10;
    const int mod=1000000007;
    const int INF=0x3f3f3f3f;
    const long long ll_INF=0x3f3f3f3f3f3f3f3fll;
    int tree[maxn<<2],dp[maxn][55],v[maxn],pre[maxn],mark[maxn],lazy[maxn<<2];
    void push_up(int rt)
    {
        tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
    }
    void build(int rt,int L,int R,int x)
    {
        tree[rt]=lazy[rt]=0;
        if(L==R)
        {  //对于dp[j][i]的值由dp[k][i]+val[k+1][j]得到,且要保证k<j,所以用dp[L-1][x-1]来给第L位置赋值
            tree[rt]=dp[L-1][x-1];  //给n个节点赋初始值
            return;
        }
        int mid=(L+R)>>1;
        build(rt<<1,L,mid,x);
        build(rt<<1|1,mid+1,R,x);
        push_up(rt);
    }
    void push_down(int rt)
    {
        if(lazy[rt])
        {
            lazy[rt<<1]+=lazy[rt];  //上一个节点的lazy值保存的是它子节点的偏移量
            lazy[rt<<1|1]+=lazy[rt];
            tree[rt<<1]+=lazy[rt];
            tree[rt<<1|1]+=lazy[rt];
            lazy[rt]=0;
        }
    }
    void update(int rt,int L,int R,int LL,int RR)
    {
        if(LL<=L && RR>=R)
        {
            lazy[rt]++;
            tree[rt]++;
            return ;
        }
        push_down(rt);
        int mid=(L+R)/2;
        if(LL<=mid)update(rt<<1,L,mid,LL,RR);
        if(RR>mid)update(rt<<1|1,mid+1,R,LL,RR);
        push_up(rt);
    }
    int query(int rt,int L,int R,int LL,int RR)
    {
        if(LL<=L && RR>=R)
        {
            return tree[rt];
        }
        push_down(rt);
        int mid=(L+R)>>1,ans=0;
        if(LL<=mid) ans=max(ans,query(rt<<1,L,mid,LL,RR));
        if(RR>mid) ans=max(ans,query(rt<<1|1,mid+1,R,LL,RR));
        return ans;
    }
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; ++i)
            scanf("%d",&v[i]);
        for(int i=1; i<=n; ++i)
        {
            pre[i]=mark[v[i]]+1;
            mark[v[i]]=i;
        }
        for(int i=1; i<=k; ++i)
        {
            build(1,1,n,i);
            for(int j=1; j<=n; ++j)
            {
                update(1,1,n,pre[j],j);
                dp[j][i]=query(1,1,n,1,j);
            }
        }
        printf("%d
    ",dp[n][k]);
        return 0;
    }

     

  • 相关阅读:
    poj 3087 直接模拟
    POJ-3126 BFS,埃式筛选及黑科技
    POJ3278-Catch That Cow
    js变量提升
    饿了么
    2分钟就能学会的【Google/百度搜索大法】了解一下?
    span标签间距
    Vue移动端项目如何使用手机预览调试
    Port 3000 is already in use
    koa2第一天 async详解
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13973957.html
Copyright © 2020-2023  润新知