zoukankan      html  css  js  c++  java
  • Codeforces Round #426 (Div. 2) D. The Bakery(线段树维护dp)

    题目链接: Codeforces Round #426 (Div. 2) D. The Bakery

    题意:

    给你n个数,划分为k段,每段的价值为这一段不同的数的个数,问如何划分,使得价值最大。

    题解:

    考虑dp[i][j]表示划分为前j个数划分为i段的最大价值,那么这就是一个n*n*k的dp,

    考虑转移方程dp[i][j]=max{dp[i][k]+val[k+1][j]},我们用线段树去维护这个max,线段树上每个节点维护的值是dp[i][k]+val[k+1][j],对于每加进来的一个数a[j],他只会影响last[a[j]]~j-1这段区间,所以线段树将这段区间加1。dp[i][j]就是区间最大值。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
     3 inline int RT(int l,int r){return l+r|l!=r;}
     4 using namespace std;
     5 
     6 const int N=40000;
     7 int n,k,mx[N*2],lazy[N*2],dp[N],a[N],la[N],pos[N];
     8 
     9 void build(int l=0,int r=n)
    10 {
    11     int rt=RT(l,r),mid=l+r>>1;lazy[rt]=0;
    12     if(l==r){mx[rt]=dp[l];return;}
    13     build(l,mid),build(mid+1,r);
    14     mx[rt]=max(mx[RT(l,mid)],mx[RT(mid+1,r)]);
    15 }
    16 
    17 void PD(int l,int r)
    18 {
    19     int rt=RT(l,r),ls=RT(l,l+r>>1),rs=RT((l+r>>1)+1,r);
    20     lazy[ls]+=lazy[rt],lazy[rs]+=lazy[rt];
    21     mx[ls]+=lazy[rt],mx[rs]+=lazy[rt];
    22     lazy[rt]=0;
    23 }
    24 
    25 void update(int L,int R,int v,int l=0,int r=n)
    26 {
    27     int rt=RT(l,r),mid=l+r>>1;
    28     if(L<=l&&r<=R){mx[rt]+=v,lazy[rt]+=v;return;}
    29     if(lazy[rt])PD(l,r);
    30     if(L<=mid)update(L,R,v,l,mid);
    31     if(R>mid)update(L,R,v,mid+1,r);
    32     mx[rt]=max(mx[RT(l,mid)],mx[RT(mid+1,r)]);
    33 }
    34 
    35 int ask(int L,int R,int l=0,int r=n)
    36 {
    37     int rt=RT(l,r),mid=l+r>>1,ans=0;
    38     if(L<=l&&r<=R)return mx[rt];
    39     if(lazy[rt])PD(l,r);
    40     if(L<=mid)ans=max(ans,ask(L,R,l,mid));
    41     if(R>mid)ans=max(ans,ask(L,R,mid+1,r));
    42     return ans;
    43 }
    44 
    45 int main(){
    46     scanf("%d%d",&n,&k);
    47     F(i,1,n)scanf("%d",a+i),pos[i]=la[a[i]],la[a[i]]=i;
    48     F(i,1,k)
    49     {
    50         build();
    51         F(j,1,n)update(pos[j],j-1,1),dp[j]=ask(0,j-1);
    52     }
    53     printf("%d
    ",dp[n]);
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    hdu 2485 Destroying the bus stations 迭代加深搜索
    hdu 2487 Ugly Windows 模拟
    hdu 2492 Ping pong 线段树
    hdu 1059 Dividing 多重背包
    hdu 3315 My Brute 费用流,费用最小且代价最小
    第四天 下载网络图片显示
    第三天 单元测试和数据库操作
    第二天 布局文件
    第一天 安卓简介
    Android 获取存储空间
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7276860.html
Copyright © 2011-2022 走看看