传送门

线段树优化dpdpdp入门题。

要求把nnn个数分成kkk段,每段价值为里面不相同的数的个数,求所有段的价值之和最大值。n≤35000,k≤50n\le35000,k\le50n≤35000,k≤50


先考虑直接暴力dpdpdp,fj,if_{j,i}fj,i​表示把前iii个分成jjj组的最优值。

显然fj,i=max⁡j−1≤k≤i−1{fj−1,k+W(k+1,i)}f_{j,i}=\max\limits_{j-1\le k\le i-1}\{f_{j-1,k}+W(k+1,i)\}fj,i​=j−1≤k≤i−1max​{fj−1,k​+W(k+1,i)}

于是就有了一个O(n2k)O(n^2k)O(n2k)的做法。

现在考虑优化求fj,i+W(k+1,i)f_{j,i}+W(k+1,i)fj,i​+W(k+1,i)的做法。

我们考虑增量法,即枚举当前层的iii的时候考虑coloricolor_icolori​对之前所有的fff的贡献。

对于这种相同颜色只考虑一次贡献的题有这么一个固定的套路:我们记当前颜色上一次出现的位置为pre,则这个颜色会对[pre+1,i]或者[pre,i-1]这一段产生贡献

对于这道题可以动态维护fj−1,k+W(k+1,j)f_{j-1,k}+W(k+1,j)fj−1,k​+W(k+1,j)这个值,因此我们最开始将fj−1,if_{j-1,i}fj−1,i​全部放到一棵线段树上面作为初始值,走到位置iii时把[prei,i−1][pre_i,i-1][prei​,i−1]维护的值全部加111即可。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=35005,K=55;
int tmp=0,a[N],f[2][N],n,k,pre[N],mp[N];
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	int mx[N<<2],add[N<<2];
	inline void pushup(int p){mx[p]=max(mx[lc],mx[rc]);}
	inline void pushnow(int p,int v){mx[p]+=v,add[p]+=v;}
	inline void pushdown(int p){if(add[p])pushnow(lc,add[p]),pushnow(rc,add[p]),add[p]=0;}
	inline void build(int p,int l,int r){
		add[p]=0;
		if(l==r){mx[p]=f[tmp^1][l];return;}
		build(lc,l,mid),build(rc,mid+1,r),pushup(p);
	}
	inline void update(int p,int l,int r,int ql,int qr,int v){
		if(ql>qr)return;
		if(ql<=l&&r<=qr)return pushnow(p,v);
		pushdown(p);
		if(qr<=mid)update(lc,l,mid,ql,qr,v);
		else if(ql>mid)update(rc,mid+1,r,ql,qr,v);
		else update(lc,l,mid,ql,mid,v),update(rc,mid+1,r,mid+1,qr,v);
		pushup(p);
	}
	inline int query(int p,int l,int r,int ql,int qr){
		if(ql>qr)return -0x3f3f3f3f;
		if(ql<=l&&r<=qr)return mx[p];
		pushdown(p);
		if(qr<=mid)return query(lc,l,mid,ql,qr);
		if(ql>mid)return  query(rc,mid+1,r,ql,qr);
		return max(query(lc,l,mid,ql,mid),query(rc,mid+1,r,mid+1,qr));
	}
	#undef lc
	#undef rc
	#undef mid
}
int main(){
	n=read(),k=read();
	memset(mp,-1,sizeof(mp));
	for(ri i=1;i<=n;++i)a[i]=read(),pre[i]=mp[a[i]],mp[a[i]]=i;
	memset(f[tmp],-0x3f,sizeof(f[tmp]));
	f[tmp][0]=0;
	for(ri tt=1;tt<=k;++tt){
		tmp^=1;
		memset(f[tmp],-0x3f,sizeof(f[tmp]));
		SGT::build(1,0,n);
		for(ri i=1;i<=n;++i){
			SGT::update(1,0,n,pre[i],i-1,1);
			f[tmp][i]=SGT::query(1,0,n,tt-1,i-1);
		}
	}
	cout<<f[tmp][n];
	return 0;
}

2019.03.09 codeforces833B. The Bakery(线段树优化dp)的更多相关文章

  1. CodeForces 834D The Bakery(线段树优化DP)

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

  2. 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 ...

  3. CF833B The Bakery 线段树,DP

    CF833B The Bakery LG传送门 线段树优化DP. 其实这是很久以前就应该做了的一道题,由于颓废一直咕在那里,其实还是挺不错的一道题. 先考虑\(O(n^2k)\)做法:设\(f[i][ ...

  4. D - The Bakery CodeForces - 834D 线段树优化dp···

    D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...

  5. Codeforces Round #426 (Div. 2) D 线段树优化dp

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

  6. BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】

    BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...

  7. [AGC011F] Train Service Planning [线段树优化dp+思维]

    思路 模意义 这题真tm有意思 我上下楼梯了半天做出来的qwq 首先,考虑到每K分钟有一辆车,那么可以把所有的操作都放到模$K$意义下进行 这时,我们只需要考虑两边的两辆车就好了. 定义一些称呼: 上 ...

  8. 【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

    题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a varian ...

  9. POJ 2376 Cleaning Shifts (线段树优化DP)

    题目大意:给你很多条线段,开头结尾是$[l,r]$,让你覆盖整个区间$[1,T]$,求最少的线段数 题目传送门 线段树优化$DP$裸题.. 先去掉所有能被其他线段包含的线段,这种线段一定不在最优解里 ...

随机推荐

  1. Linux 下配置 nginx + 两个 tomcat 的负载均衡

    前提:已经安装了 nginx 和两个 tomcat 1.修改 nginx.conf 配置文件    1)在 http{} 节点之间添加 upstream 配置 2)修改 nginx 的监听端口,默认是 ...

  2. Prometheus

    官方网址:https://prometheus.io/ GitHub网址:https://github.com/prometheus/prometheus 软件下载地址:https://prometh ...

  3. LevelDB源码分析-Bloom Filter

    Bloom Filter bloom filter是leveldb中用来在一个block中检测key是否存在的工具,主要在BloomFilterPolicy类中实现: class BloomFilte ...

  4. gradle问题汇总

    问题:从SVN下载到本地后,gradle无法同步,报错如下:Failed to resolve: support-core-utilsFailed to resolve: support-media- ...

  5. 结对项目-WordCount

    结对作业: 成员:201631062115(me),201631062613(partner) 代码地址:https://gitee.com/ackary/WordCount 作业的链接地址:http ...

  6. 聊聊JMM

    JMM是什么? JMM 全称 Java memory model ,直译过来就是Java内存模型,这里注意了,指到并不是JVM中的内存分布新生代.老年代.永久代这些,当然也不是 程序计数器(PC).j ...

  7. Linux系统常见的压缩与打包命令

    常见的压缩文件扩展名 1.*.Z          compress程序压缩的文件 2.*.gz         gzip程序压缩的文件 3..bz2        bzip2程序压缩的文件 4..t ...

  8. webpack 4.0配置2

    上个博客记录了webpack 的基本配置今天主要是css-loader的介绍,包括单独提出css,压缩css.js文件 这里使用的插件npm 地址:https://www.npmjs.com/pack ...

  9. Excel基本操作

    一.excel公式下拉 1.选择最长一列excel ,按CTRL+↓移到最后一个单元格,2光标移到下拉公式的那一列,3.再按CTRL+SHIFT+↑,4.再按CTRL+D 二.输入身份证号等长数字 方 ...

  10. selenium使用技巧

    标签(空格分隔): selenium 我们进行selenium的时候,就是通过webdriver,对浏览器做一些操作的: webdriver,除了find操作,之外还有哪些方法和属性呢? 1.获取当前 ...