Codeforces Round #426 (Div. 2) D The Bakery(线段树 DP)
2.5 seconds
256 megabytes
standard input
standard output
Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredients and a wonder-oven which can bake several types of cakes, and opened the bakery.
Soon the expenses started to overcome the income, so Slastyona decided to study the sweets market. She learned it's profitable to pack cakes in boxes, and that the more distinct cake types a box contains (let's denote this number as the value of the box), the higher price it has.
She needs to change the production technology! The problem is that the oven chooses the cake types on its own and Slastyona can't affect it. However, she knows the types and order of n cakes the oven is going to bake today. Slastyona has to pack exactly k boxes with cakes today, and she has to put in each box several (at least one) cakes the oven produced one right after another (in other words, she has to put in a box a continuous segment of cakes).
Slastyona wants to maximize the total value of all boxes with cakes. Help her determine this maximum possible total value.
The first line contains two integers n and k (1 ≤ n ≤ 35000, 1 ≤ k ≤ min(n, 50)) – the number of cakes and the number of boxes, respectively.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ n) – the types of cakes in the order the oven bakes them.
Print the only integer – the maximum total value of all boxes with cakes.
4 1
1 2 2 1
2
7 2
1 3 3 1 4 4 4
5
8 3
7 7 8 7 7 8 1 7
6
In the first example Slastyona has only one box. She has to put all cakes in it, so that there are two types of cakes in the box, so the value is equal to 2.
In the second example it is profitable to put the first two cakes in the first box, and all the rest in the second. There are two distinct types in the first box, and three in the second box then, so the total value is 5.
【题意】给你一个序列,然后在原来的顺序基础上将这些数分成K份,每一份至少一个数,然后对于每一份,将数的种数累加,求累加和最大值。
【分析】如果n小一些的话,我们可以n方DP做,DP[i][j]表示在i这个地方将前面分成k份的最大值,那么dp[i][j]=dp[k][j-1]+(k+1~j的数的种数),
但是N太大。。。于是我们想到线段树。线段树的维护这个区间内每一个位置的dp值+这个位置到我当前dp到的位置的数的种数,然后对这个区间取最大值。当我们dp到i时,我们将a[i]上一次出现的位置+1~i这个区间更新+1,然后查询1~i的最大值即可。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 3e4+;;
const int M = ;
const int mod = 1e9+;
const double pi= acos(-1.0);
typedef pair<int,int>pii;
int n,k,ans;
int a[N],mx[N*],lazy[N*];
int pre[N],pos[N],dp[N];
void pushUp(int rt){
mx[rt]=max(mx[rt<<],mx[rt<<|]);
}
void pushDown(int rt){
if(lazy[rt]){
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
mx[rt<<]+=lazy[rt];
mx[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void build(int l,int r,int rt){
lazy[rt]=;
if(l==r){
mx[rt]=dp[l-];
return;
}
int mid=(l+r)>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
pushUp(rt);
}
void upd(int L,int R,int l,int r,int x,int rt){
if(L<=l&&r<=R){
mx[rt]+=x;
lazy[rt]+=x;
return;
}
pushDown(rt);
int mid=(l+r)>>;
if(L<=mid)upd(L,R,l,mid,x,rt<<);
if(R>mid) upd(L,R,mid+,r,x,rt<<|);
pushUp(rt);
}
int qry(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return mx[rt];
}
pushDown(rt);
int ret=,mid=(l+r)>>;
if(L<=mid)ret=max(ret,qry(L,R,l,mid,rt<<));
if(R>mid)ret=max(ret,qry(L,R,mid+,r,rt<<|));
return ret;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
pre[i]=pos[a[i]];
pos[a[i]]=i;
}
for(int i=;i<=k;i++){
build(,n,);
for(int j=;j<=n;j++){
upd(pre[j]+,j,,n,,);
dp[j]=qry(,j,,n,);
}
}
printf("%d\n",dp[n]);
}
Codeforces Round #426 (Div. 2) D The Bakery(线段树 DP)的更多相关文章
- Codeforces Round #426 (Div. 2) D. The Bakery 线段树优化DP
D. The Bakery Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought req ...
- Codeforces Round #587 (Div. 3) F Wi-Fi(线段树+dp)
题意:给定一个字符串s 现在让你用最小的花费 覆盖所有区间 思路:dp[i]表示前i个全覆盖以后的花费 如果是0 我们只能直接加上当前位置的权值 否则 我们可以区间询问一下最小值 然后更新 #incl ...
- Codeforces Round #426 (Div. 1) B The Bakery (线段树+dp)
B. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...
- Codeforces Round #603 (Div. 2) E. Editor(线段树)
链接: https://codeforces.com/contest/1263/problem/E 题意: The development of a text editor is a hard pro ...
- Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq
B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/pro ...
- 【动态规划】【线段树】 Codeforces Round #426 (Div. 1) B. The Bakery
给你一个序列,让你划分成K段,每段的价值是其内部权值的种类数,让你最大化所有段的价值之和. 裸dp f(i,j)=max{f(k,j-1)+w(k+1,i)}(0<=k<i) 先枚举j,然 ...
- Codeforces Round #546 (Div. 2) E 推公式 + 线段树
https://codeforces.com/contest/1136/problem/E 题意 给你一个有n个数字的a数组,一个有n-1个数字的k数组,两种操作: 1.将a[i]+x,假如a[i]+ ...
- Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并
D. Developing Game Pavel is going to make a game of his dream. However, he knows that he can't mak ...
- Codeforces Round #275 Div.1 B Interesting Array --线段树
题意: 构造一个序列,满足m个形如:[l,r,c] 的条件. [l,r,c]表示[l,r]中的元素按位与(&)的和为c. 解法: 线段树维护,sum[rt]表示要满足到现在为止的条件时该子树的 ...
随机推荐
- 【BZOJ1598】牛跑步 [A*搜索]
牛跑步 Time Limit: 10 Sec Memory Limit: 162 MB[Submit][Status][Discuss] Description BESSIE准备用从牛棚跑到池塘的方 ...
- bzoj 2144: 跳跳棋——倍增/二分
Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...
- 基本控件文档-UISlider属性---iOS-Apple苹果官方文档翻译
本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/C ...
- bzoj 1197 DP
我们可以将这个问题转化为在n维空间中一共放m个n维球,求这m个球最多将这个空间分为不同的几个部分. 那么我们设w[i][j]代表i为空间放j个球分为的部分,那么w[i][j]=w[i][j-1]+w[ ...
- E题hdu 1425 sort
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1425 sort Time Limit: 6000/1000 MS (Java/Others) M ...
- linux下暴力破解工具hydra【转】
一.简介 Number one of the biggest security holes are passwords, as every password security study shows. ...
- 10.异步SRAM的FPGA读写操作
异步SRAM:正如其名,不是与特定的时钟信号同步运行,而是根据输入信号的状态运行的.因为没有信号表明读取时已确定了有效数据,也没有信号表明写入时已接收到数据,所以,需要获取制造商的数据手册,根据时序图 ...
- 51/52单片机 TCON控制字及TMOD寄存器
转载:http://blog.csdn.net/u010698858/article/details/44118157 TCON:定时器控制寄存器 寄存器地址88H,位寻址8FH-88H. 位地址 8 ...
- C语言string转int
再不用atoi函数接口时,将字符串型转换成整型. 例如:将字符串型“158”转换成整型158 int String2Int(char * buff) { ; ; '; index++) { value ...
- jquery获取元素索引值index()的例子
如果参数是一组DOM元素或者jQuery对象,那么返回值就是传递的元素相对于原先集合的位置. 如果参数是一个选择器,那么返回值就是原先元素相对于选择器匹配元素中的位置.如果找不到匹配的元素,则返回-1 ...