传送门

线段树优化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. 排序大集合java

    今日面试被问到排序问题,发现自己的不足,特来查漏补缺: 首先是各大排序算法的总结表 排序算法大合集  排序算法 平均时间复杂度 最好情况 最坏情况 空间复杂度 稳定性 冒泡排序 Ο(n2) Ο(n) ...

  2. laravel passport加密jwt格式的access_token中的sub(user_id)字段

    在很多需求我们不希望别人知道用户在我们表中的 user_id :但是又想用数据库的自增 id 功能:一般时候在取出用户后加密 user_id 加密即可:但是总有那么几个不经意间就可能把我们的 user ...

  3. Redis 数据类型归纳

    Redis的数据类型从整体上看,都是Key-Value键值对的模型,数据类型更确切地说,应该是Value的数据类型,比如string,set,list等,都是key值对应的Value的数据集合格式.不 ...

  4. ansible批量自动安装LNMP

  5. nodejs设置跨域访问

    //设置跨域访问app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", ...

  6. vue项目结构搭建

    1安装node.js,已集成npm 2.临时使用淘宝镜像 npm --registry https://registry.npm.taobao.org install express 3.instal ...

  7. Numpy一文全了解

    1,Numpy是一个python包,它是一个由多维数组对象和处理数组的例程集合组成的库. 2.   Numpy的操作:(1)数组的算数和逻辑运算 :(2)傅里叶变换和用于图形操作  (3)与线性代数有 ...

  8. Spring:事务

    摘要 本文摘抄了Spring事务相关的一些理论,主要讲述事务的特性.事务的传播行为.事务的隔离规则. 关键词:事务特性,事务传播,事务隔离 一.什么是事务 事务是用来保证数据的完整性和一致性,正如金钱 ...

  9. Android辅助开发工具合集

    https://github.com/389273716/android-skill-summary/blob/master/开发工具使用指南/辅助开发工具.md

  10. js及vue监听键盘回车事件

    js document.onkeydown = (event) => { var e = event || window.event; if(e && e.keyCode==13 ...