OwO http://codeforces.com/contest/833/problem/B

  首先读入的时候把数据读入到2 ~ n+1的位置(因为线段树处理不到0,所以后移了一格)

  dp[i][j]代表处理到第i个位置为止,分j段能得到的最大值

  lst[i]记录第与第i个蛋糕一样的蛋糕出现的上一个位置

  则,显然dp[i][j]=min(dp[i-t][j-1]+(从i-t+1到i位置的不同种类的蛋糕个数))

  记对每一段的值有贡献的点为同一段每种类型蛋糕最左边的点(比如其中一段AAFBCCDBAB,那么对这一段有贡献的B为F后面的那个B,因为他最先出现)

  那么可以从小到大枚举k

  每一次枚举的时候根据k-1时的dp值建一个线段树,从左往右遍历蛋糕数组,扫到第i个蛋糕的时候,线段树上第t个点表示的是上一段的右端点取t时(即这一段起点取t+1)dp[i][k]的取值,那么显然这是一个区间最大值得线段树

  维护的话,扫到第i个蛋糕的时候,线段树上(lst[i],i-1)区间的值+1,因为第k-1个区间的右端点取t取(lst[i],i-1)上的点时(即第k个区间为(t+1,i),包括了第i个蛋糕,而且第i个蛋糕为该区间第一个该种蛋糕),cake[i]种类对第k个区间有贡献

  查询的话,扫到第i个蛋糕的时候,查询第k-1段右节点可以选的那一段的就可以了

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath> using namespace std; const int M=5e4; int dp[M][60],nowk;
int tree[M*3],tag[M*3]; void build(int rt,int li,int ri)
{
tag[rt]=0;
if(li==ri)
{
tree[rt]=dp[li][nowk];
return ;
}
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
build(lc,li,mid);
build(rc,mid+1,ri);
tree[rt]=max(tree[lc],tree[rc]);
} void pushdown(int rt,int li,int ri)
{
if(li==ri)
{
tag[rt]=0;
return ;
}
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
tree[lc]+=tag[rt];
tree[rc]+=tag[rt];
tag[lc]+=tag[rt];
tag[rc]+=tag[rt];
tag[rt]=0;
} void update(int rt,int li,int ri,int lq,int rq,int val) //add
{
if(lq<=li && ri<=rq)
{
tag[rt]+=val;
tree[rt]+=val;
return ;
}
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
if(tag[rt])
pushdown(rt,li,ri);
if(mid>=lq)
update(lc,li,mid,lq,rq,val);
if(mid+1<=rq)
update(rc,mid+1,ri,lq,rq,val);
tree[rt]=max(tree[lc],tree[rc]);
} int query(int rt,int li,int ri,int lq,int rq) //get max
{
int ret=-1e9-7;
if(lq<=li && ri<=rq)
return tree[rt];
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
if(tag[rt])
pushdown(rt,li,ri);
if(mid>=lq)
ret=max(ret,query(lc,li,mid,lq,rq));
if(mid+1<=rq)
ret=max(ret,query(rc,mid+1,ri,lq,rq));
return ret;
} int n,k;
int cake[M];
int lst[M],tmp[M];
int ans; void init()
{
int i,j;
for(i=1;i<=n+1;i++)
tmp[i]=1;
for(i=2;i<=n+1;i++)
{
lst[i]=tmp[cake[i]];
tmp[cake[i]]=i;
}
ans=0;
memset(dp,0,sizeof(dp));
} int main()
{
int i,j,tmp;
scanf("%d%d",&n,&k);
for(i=2;i<=n+1;i++)
scanf("%d",&cake[i]);
init();
n++;
for(i=1;i<=k;i++)
{
nowk=i-1;
build(1,1,n);
for(j=i+1;j<=n;j++)
{
update(1,1,n,lst[j],j-1,1);
tmp=query(1,1,n,i,j-1);
// cout<<tmp<<endl;
dp[j][i]=max(dp[j][i],tmp);
}
}
ans=dp[n][k];
cout<<ans<<endl;
return 0;
}

  

Codeforces 833B / B34D The Bakery的更多相关文章

  1. codeforces 834 D. The Bakery

    codeforces 834 D. The Bakery(dp + 线段树优化) 题意: 给一个长度为n的序列分成k段,每段的值为这一段不同数字的个数,最大化划分k端的值 $n <= 35000 ...

  2. Codeforces 833B The Bakery dp线段树

    B. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  3. Codeforces 833B The Bakery(主席树 + 决策单调性优化DP)

    题目链接 The Bakery 题目大意:目标是把$n$个数分成$k$组,每个组的值为这个组内不同的数的个数,求$k$个组的值的和的最大值. 题目分析: 这道题我的解法可能和大众解法不太一样……我用主 ...

  4. CodeForces - 833B The Bakery

    题解: 线段树经典应用 首先暴力$f[i][j]$表示考虑前i位分成j段的最大值 转移$f[k][j-1]+cost(k+1,i)$枚举k转移 不同数的经典套路就是从它到它前驱这一段 于是维护每个数前 ...

  5. Codeforces.833B.The Bakery(线段树 DP)

    题目链接 \(Description\) 有n个数,将其分为k段,每段的值为这一段的总共数字种类,问最大总值是多少 \(Solution\) DP,用\(f[i][j]\)表示当前在i 分成了j份(第 ...

  6. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  7. Codeforces Round #368 (Div. 2) B. Bakery (模拟)

    Bakery 题目链接: http://codeforces.com/contest/707/problem/B Description Masha wants to open her own bak ...

  8. Codeforces 834D The Bakery【dp+线段树维护+lazy】

    D. The Bakery time limit per test:2.5 seconds memory limit per test:256 megabytes input:standard inp ...

  9. Codeforces 834D The Bakery - 动态规划 - 线段树

    Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredient ...

随机推荐

  1. Redis(1.1)linux下安装redis

    一.常见安装方式 [0]环境 OS:CentOS7.5 Redis:4.0.14 yum源:本地源 [1]检查安装 gcc 依赖环境 gcc -v#如果没安装会报错类似于 command not fi ...

  2. less的引用及公共变量的抽离

    一.什么是less? less是什么自然不用多言,乃一个css预编译器,可以扩展css语言,添加功能如如允许变量(variables),混合(mixins),函数(functions) 和许多其他的技 ...

  3. QT目录模型QDirModel的使用(一个model同时连接tree,list,table)

    3#include <QApplication>#include <QAbstractItemModel>#include <QAbstractItemView># ...

  4. 使用JavaScript和React编写原生移动应用

    使用JavaScript和React编写原生移动应用 React Native使你只使用JavaScript也能编写原生移动应用. 它在设计原理上和React一致,通过声明式的组件机制来搭建丰富多彩的 ...

  5. 进阶Java编程(3)线程的同步与死锁

    线程的同步与死锁 1,同步问题引出 在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,对于当多个线程访问统一资源的时候如果处理不当就会产生数据的错误 ...

  6. asp.net 3.三层架构

    1.新建项目和类库 CZBK.ItcastProject (空白项目) CZBK.ItcastProject.BLL (类库) -- 逻辑业务 CZBK.ItcastProject.Common (类 ...

  7. C#面向对象9 字符串

    1.字符串的不可变性 当你给一个字符串重新赋值之后,老的值并没有销毁,而是重新开辟了一块空间(堆)存储新的值. **当程序结束后,GC扫描整个内存,如果发现有的空间没有被指向,则立即把它销毁. 示意图 ...

  8. Fonour.AspnetCore 生成SQL SERVER数据库

    Install-Package EntityFramework Add-Migration InitialCreate Update-Database

  9. Makefile速查笔记

    Makefile速查笔记 Makefile中的几个调试方法 一. 使用 info/warning/error 增加调试信息 a. $(info "some text")打印 &qu ...

  10. java中成员变量和局部变量在内存中的分配

    对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量:局部变量就是方法或语句块内部定义的变量.局部变量必须初始化. 形式参数是局部变量,局部变量中基础数据类型的引用和值都存储在栈中,对象引 ...