zoukankan      html  css  js  c++  java
  • CF833B The Bakery

    题目大意:给出n个数的数列,其中保证1<=ai<=n,使其分成m份,使得每一段字符集大小相加最大,求最大值。

    考场上跪了,回来一想发现是线段树维护dp:

    原dp:dp[ i ][ j ] = max ( dp[ j ][ k-1 ] + num[ j+1 ][ i ]);

    然后发现线段树可以维护,即将等号右边的那一段扔到线段树中,时间复杂度为 O( nlogn )。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 35050
    int n,K;
    int a[N],las[N],nxt[N];
    int v[N<<2],mrk[N<<2];
    int dp[51][N];
    void update(int u)
    {
        v[u]=max(v[u<<1],v[u<<1|1]);
    }
    void add(int u,int d)
    {
        v[u]+=d;
        mrk[u]+=d;
    }
    void pushdown(int u)
    {
        if(mrk[u])
        {
            add(u<<1,mrk[u]);
            add(u<<1|1,mrk[u]);
            mrk[u]=0;
        }
    }
    void build(int l,int r,int u,int k)
    {
        mrk[u]=0;
        if(l==r)
        {
            v[u]=dp[k][l-1];
            return ;
        }
        int mid = (l+r)>>1;
        build(l,mid,u<<1,k);
        build(mid+1,r,u<<1|1,k);
        update(u);
    }
    void insert(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)
        {
            add(u,1);
            return ;
        }
        pushdown(u);
        int mid = (l+r)>>1;
        if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr);
        else if(qr<=mid)insert(l,mid,u<<1,ql,qr);
        else insert(l,mid,u<<1,ql,mid),insert(mid+1,r,u<<1|1,mid+1,qr);
        update(u);
    }
    int query(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)return v[u];
        pushdown(u);
        int mid = (l+r)>>1;
        if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
        else if(qr<=mid)return query(l,mid,u<<1,ql,qr);
        else return max(query(l,mid,u<<1,ql,mid),query(mid+1,r,u<<1|1,mid+1,qr));
    }
    int main()
    {
    //    freopen("handsome.in","r",stdin);
    //    freopen("handsome.out","w",stdout);
        scanf("%d%d",&n,&K);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            nxt[i]=las[a[i]];
            las[a[i]]=i;
        }
        for(int k=1;k<=K;k++)
        {
            build(1,n,1,k-1);
            for(int i=1;i<=n;i++)
            {
                insert(1,n,1,nxt[i]+1,i);
                dp[k][i]=query(1,n,1,1,i);
            }
        }
        printf("%d
    ",dp[K][n]);
        return 0;
    }
  • 相关阅读:
    pgsql 时间转时间戳
    java SHA-1加密
    java 输出json文件
    按照指定字符串截取文本
    java 科学计数法转换
    【原创】几个常用机场的对比
    【原创】Google Cloud服务器路由分析
    批量转换文件Unicode到中文
    博客搬家
    关于zookeeper
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9736629.html
Copyright © 2011-2022 走看看