CF833B-线段树优化DP

题意

将一个长为\(n\)的序列分成\(k\)段,每段贡献为其中不同数字的个数,求最大贡献和。

思路

此处感谢@gxy001 聚铑的精彩讲解

先考虑暴力DP,可以想到一个时空复杂度\(O(n^2k)\)的方法,即记录前i个数字分成了j段。我们现在来思考几个问题来优化这个操作:

  1. 对于一个数字,它对那些地方实际有贡献?
  2. 每次分割出一个区间段对后续操作有影响的位置在哪?
  3. 每次转移都从哪些地方继承?

下来一一解答这些问题。

  1. 对于一个数字,它能产生贡献的区间其实就是该数字上一次出现的位置的后一位到它本身的位置。
  2. 对于每次划分,它以前的位置的贡献已经被考虑,所以我们只能考虑后面的位置。
  3. 相应的,每次转移会继承前面所有DP值的最大值

那么我们可以将k提出来,每次循环继承上一次所有的dp值。因为只考虑从前面转移dp值,所以不会对之前的决策产生影响,所以是正确的。

看看1、3问题的答案,是不是想到了RMQ和区间赋值?

于是我们可以通过线段树来实现DP优化。

具体来讲,迭代k次,每次线段树更新为上一次序列的dp值,然后从前往后扫,每个数会对其上述区间产生1的贡献,转移继承前面所有dp值的最大值即可。

时间复杂度将一维优化为log。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=35005;
int n,k,cur[maxn],pre[maxn],f[maxn][60];
struct SegmentTree{
#define ls (ro<<1)
#define rs (ro<<1|1)
struct tree{
int l,r,tag,v;
}e[maxn<<2];
inline void pushup(int ro){
e[ro].v=max(e[ls].v,e[rs].v);
}
inline void pushdown(int ro){
e[ls].tag+=e[ro].tag;e[rs].tag+=e[ro].tag;
e[ls].v+=e[ro].tag;e[rs].v+=e[ro].tag;
e[ro].tag=0;
}
void build(int ro,int l,int r){
e[ro].l=l,e[ro].r=r;
if(l==r)return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void rebuild(int tim,int ro){
int l=e[ro].l,r=e[ro].r;
e[ro].tag=0;
if(l==r){
e[ro].v=f[l][tim];return;
}
rebuild(tim,ls);rebuild(tim,rs);
pushup(ro);
}
void update(int ro,int x,int y){
int l=e[ro].l,r=e[ro].r;
if(l>=x and r<=y){
e[ro].v+=1;
e[ro].tag+=1;return;
}
pushdown(ro);
int mid=l+r>>1;
if(mid>=x)update(ls,x,y);
if(mid<y)update(rs,x,y);
pushup(ro);
}
int query(int ro,int x,int y){
int l=e[ro].l,r=e[ro].r;
if(l==x and r==y)return e[ro].v;
pushdown(ro);
int mid=l+r>>1;
if(mid<x)return query(rs,x,y);
else if(mid>=y)return query(ls,x,y);
else return max(query(ls,x,mid),query(rs,mid+1,y));
}
#undef ls
#undef rs
}T;
inline void work(){
n=read(),k=read();
for(int x,i=1;i<=n;i++)x=read(),pre[i]=cur[x],cur[x]=i;
T.build(1,0,n);
for(int i=1;i<=k;i++){
T.rebuild(i-1,1);
for(int x=1;x<=n;x++) T.update(1,pre[x],x-1),f[x][i]=T.query(1,0,x-1);
}
printf("%d",f[n][k]);
}
}
signed main(){
star::work();
return 0;
}

CF833B-线段树优化DP的更多相关文章

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

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

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

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

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

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

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

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

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

  6. 洛谷$P2605\ [ZJOI2010]$基站选址 线段树优化$dp$

    正解:线段树优化$dp$ 解题报告: 传送门$QwQ$ 难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$ 先考虑暴力$dp$?就设$f_{i,j}$表示 ...

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

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

  8. 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点

    容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...

  9. Codeforces 1603D - Artistic Partition(莫反+线段树优化 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 学 whk 时比较无聊开了道题做做发现是道神题( 介绍一种不太一样的做法,不观察出决策单调性也可以做. 首先一个很 trivial 的 o ...

  10. 2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP)

    2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP) https://www.luogu.com.cn/problem/P1848 题意: 当农夫约翰闲 ...

随机推荐

  1. Spring Cloud系列(三):服务消费与负载均衡

    上一篇介绍了服务提供者,有了注册中心和服务提供者,我们就可以进行服务消费了.Spring Cloud可以通过RestTemplate+Ribbon和Feign这两种方式消费服务. 我们仍然在上一篇的项 ...

  2. sync.waitgroup ----等待goroutine的执行完成

    可以尝试改变wg.add里的值,改变wg.wait,或者wg.done的出现次数以及位置. 感受它的使用

  3. SpringCloud Alibaba实战(6:nacos-server服务搭建)

    源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 大家好,我是三分恶. 这一节我们来学习SpringCloud Alibaba体系中一 ...

  4. Java代码优化:使用构造函数和使用一个个setter的效率差别

    在对Java代码进行优化的时候,想方设法的要提高整体的效率,使用JProfiler看代码的时间占比,然后,看看哪些部分是可以优化的,减少运行时间的.下面有这么几个方向. 1. 能使用构造函数一步到位的 ...

  5. EVB_Air724UG_A13开发板使用指南

      Air724 是上海合宙物联网于2020年3月下旬发布的一款基于UIS8910DM芯片组的物联网通讯模块. 模块通讯性能优越,符合Cat1通讯标准,支持最大下行速率 10Mbps 和最大上行速率5 ...

  6. 【dog与lxy】8.25题解-land

    land 题目描述 dog终于有了一块领地,但是现在可怜的dog面临着lxy的入侵,于是他决定在自己的领地设置炮楼来保卫自己免受QJ.现在dog找到它可以在领地上设置炮楼的N个地点.但是留给dog的时 ...

  7. Oracle不知道用户密码情况下,如何在不更改密码的前提下解锁用户或者延期密码有效期

    1.问题描述: 生产环境,zabbix告警业务用户密码即将过期,但是如何不知道业务用户密码的情况下来解决该问题? 2.实验一: 1)创建新的用户test,并授予test resource角色和conn ...

  8. 循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示

    在BootstrapVue组件库里面,提供了很多对Bootstrap同等类似的组件封装,其中图片轮播可以采用b-carousel-slide组件实现,而有一些小的图片,如客户/合作伙伴Logo或者友情 ...

  9. WEB安全漏洞扫描与处理(下)——安全报告分析和漏洞处理

    1 AppScan生成的安全报告分析 利用AppScan生成安全报告,可以提前对要生成的安全报告的内容进行选择,如下图,最全的安全报告内容,包括摘要,安全性问题,咨询和修订建议,应用程序数据等. 生成 ...

  10. VLAN协议与三层交换机 (Access/Trubk/Hrbrid)

    VLAN协议与三层交换机(Access/Trunk/Hybrid) 目录 一.VLAN概述 1.1.分割广播域 1.2.VLAN的优势 1.3.静态VLAN 二.Trunk的作用 2.1.概念 2.2 ...