博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019.03.09 codeforces833B. The Bakery(线段树优化dp)
阅读量:5252 次
发布时间:2019-06-14

本文共 2462 字,大约阅读时间需要 8 分钟。

线段树优化dpdpdp入门题。
要求把nnn个数分成kkk段,每段价值为里面不相同的数的个数,求所有段的价值之和最大值。n≤35000,k≤50n\le35000,k\le50n35000,k50


先考虑直接暴力dpdpdpfj,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=j1ki1max{
fj1,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)fj1,k+W(k+1,j)这个值,因此我们最开始将fj−1,if_{j-1,i}fj1,i全部放到一棵线段树上面作为初始值,走到位置iii时把[prei,i−1][pre_i,i-1][prei,i1]维护的值全部加111即可。

代码:

#include
#define ri register intusing 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<

转载于:https://www.cnblogs.com/ldxcaicai/p/10582382.html

你可能感兴趣的文章
win10 bcdedit加入vhdx启动
查看>>
Linux 黑白界面显示
查看>>
ActiveMQ学习系列(四)----消息持久化到mysql
查看>>
JavaScript设计模式基础之面向对象的JavaScript(一)
查看>>
RabbitMQ-从基础到实战(4)— 消息的交换(中)
查看>>
mysql 索引数据结构及原理
查看>>
01.Hibernate入门
查看>>
Ubuntu 16.0.4开启 log-bin
查看>>
mongoDB的学习【小白的福音】
查看>>
软件工程的实践项目的自我目标
查看>>
sql server日期时间转字符串
查看>>
经典排序算法(PHP)
查看>>
Spring boot中Spring-Data-JPA操作MySQL数据库时遇到的错误(一)
查看>>
django实现SSO
查看>>
adidas crazylight 2018 performance analysis review
查看>>
influxDb数据备份
查看>>
手动创建一张表
查看>>
算法与并行计算(世界著名计算机教材精选)
查看>>
centos7 网络不通
查看>>
[bzoj1662] [Usaco2006 Nov]Round Numbers 圆环数
查看>>