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. kettle转换设置变量,校验输出新变量

    背景:有很多小的转换需要串联起来,如果前一个执行成功,后面继续接着执行,如果执行等待中,就让程序等一会再次获取数据分析,如果失败就中止,成功就进行下一个转换,以此类推.... 需求:通过job把参数传 ...

  2. Spring的Bean的生命周期(大众版)

      距离上一次写Spring源码解析,已经过去了快要好几个月了,主要原因还是Spring的源码解析类文章太难写了,不像我先前写的什么CAS源码,AQS源码,LinkedBlockingQueue等等, ...

  3. PBOC第八部分和第十一部分关于TYPEA总结(二)——传输协议(ISO14443-4)

    二.传输协议(ISO14443-4)(8,P50 11,P30) 1.选择应答请求(RATS) 使用RATS命令和PICC协商通讯的最大帧长度(FSD和FSC).帧等待时间(FWT)和启动帧保护时间( ...

  4. 并不对劲的复健训练-CF1187D

    题目大意 有两个长度为\(n\)的序列\(a_1,...,a_n\),\(b_1,...,b_n\)(\(a,b\leq n\leq 3\times 10^5\) ).一次操作是选取 \([l,r]\ ...

  5. fork 代码进阶

    fork进阶知识 先看一份代码: [cpp] view plain copy /* *  fork_test.c *  version 2 *  Created on: 2010-5-29 *     ...

  6. opencv+ linux + cmake 生成 opencv静态库

    您可以省去如下步骤,直接下载我编译好的: http://download.csdn.net/detail/u011258240/9710331 一.编译opencv2.4  不带contrib 1. ...

  7. 爬虫中什么是requests

    print(response.text) #响应的信息 print(response.headers) #获取响应头 print(response.status_code) #响应状态码 print( ...

  8. 深入理解hadoop之排序

    MapReduce的排序是默认按照Key排序的,也就是说输出的时候,key会按照大小或字典顺序来输出,比如一个简单的wordcount,出现的结果也会是左侧的字母按照字典顺序排列.下面我们主要聊聊面试 ...

  9. [leetcode] 题解记录 11-20

    博客园markdown太烂, 题解详情https://github.com/TangliziGit/leetcode/blob/master/solution/11-20.md Leetcode So ...

  10. Base64加密后有换行回车的解决办法

    据RFC 822规定,每76个字符,还需要加上一个回车换行 有时就因为这些换行弄得出了问题,解决办法如下,替换所有换行和回车 String bTemp = Base64.encodeBase64Str ...