题目链接:https://vjudge.net/problem/CodeForces-833B

题意:
给长度为n的数组a,和一个整数k
要求把数组分成连续的k段,每段的权值是该段中不同数的个数,
输出最大权值和。
数据范围:n<=35000,k<=min(n,50),1<=a(i)<=n

题解:
很容易想到暴力dp的方式
dp[i][j]:前1-i个数分成了j个段
那么dp[i][j]=max(dp[k][j-1]+val[k+1][i]) //val[i][j]表示区间i-j中不同数的个数
这个方法的复杂度就是O(n^2*k),很显然不可行

那么我们可以把找max(dp[k][j-1]+val[k+1][i])这个过程使用线段树优化掉
我们可以从1-n的数分成j段建立一颗线段树,也就是对dp[x][j](1<=x<=n)建一颗线段树维护这n个数的最大值
然后对dp[i][j]的求解可以从维护dp[x][j-1]这一颗树中查找区间【1,(i-1)】的最大值

但是有一点不对,因为dp[i][j]由dp[k][j-1]和val[k+1][i]两部分构成,所以只有dp[k][j-1]最大并不一定可以得到
dp[i][j]最大,所以我们就要想办法处理一下维护dp[x][j]的线段树,让线段树维护这两部分的和

对于下面的一组数(下标从1开始)
7 8 1 7
第二个7的有效区域是[2,4],那么我们可以在原有维护dp[x][j]的线段树基础上,线段树在[2,4]这个区间的值都加1
这样的话就相当于让线段树维护了两部分的和


/*
题意:
给长度为n的数组a,和一个整数k
要求把数组分成连续的k段,每段的权值是该段中不同数的个数,
输出最大权值和。
数据范围:n<=35000,k<=min(n,50),1<=a(i)<=n 题解:
很容易想到暴力dp的方式
dp[i][j]:前1-i个数分成了j个段
那么dp[i][j]=max(dp[k][j-1]+val[k+1][i]) //val[i][j]表示区间i-j中不同数的个数
这个方法的复杂度就是O(n^2*k),很显然不可行 那么我们可以把找max(dp[k][j-1]+val[k+1][i])这个过程使用线段树优化掉
我们可以从1-n的数分成j段建立一颗线段树,也就是对dp[x][j](1<=x<=n)建一颗线段树维护这n个数的最大值
然后对dp[i][j]的求解可以从维护dp[x][j-1]这一颗树中查找区间【1,(i-1)】的最大值 但是有一点不对,因为dp[i][j]由dp[k][j-1]和val[k+1][i]两部分构成,所以只有dp[k][j-1]最大并不一定可以得到
dp[i][j]最大,所以我们就要想办法处理一下维护dp[x][j]的线段树,让线段树维护这两部分的和 对于下面的一组数(下标从1开始)
7 8 1 7
第二个7的有效区域是[2,4],那么我们可以在原有维护dp[x][j]的线段树基础上,线段树在[2,4]这个区间的值都加1
这样的话就相当于让线段树维护了两部分的和 */ #include <cstdio>
#include <cstring>
#include <iostream>
#include<algorithm>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int maxn=5e4+10;
const int mod=1000000007;
const int INF=0x3f3f3f3f;
const long long ll_INF=0x3f3f3f3f3f3f3f3fll;
int tree[maxn<<2],dp[maxn][55],v[maxn],pre[maxn],mark[maxn],lazy[maxn<<2];
void push_up(int rt)
{
tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
void build(int rt,int L,int R,int x)
{
tree[rt]=lazy[rt]=0;
if(L==R)
{ //对于dp[j][i]的值由dp[k][i]+val[k+1][j]得到,且要保证k<j,所以用dp[L-1][x-1]来给第L位置赋值
tree[rt]=dp[L-1][x-1]; //给n个节点赋初始值
return;
}
int mid=(L+R)>>1;
build(rt<<1,L,mid,x);
build(rt<<1|1,mid+1,R,x);
push_up(rt);
}
void push_down(int rt)
{
if(lazy[rt])
{
lazy[rt<<1]+=lazy[rt]; //上一个节点的lazy值保存的是它子节点的偏移量
lazy[rt<<1|1]+=lazy[rt];
tree[rt<<1]+=lazy[rt];
tree[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void update(int rt,int L,int R,int LL,int RR)
{
if(LL<=L && RR>=R)
{
lazy[rt]++;
tree[rt]++;
return ;
}
push_down(rt);
int mid=(L+R)/2;
if(LL<=mid)update(rt<<1,L,mid,LL,RR);
if(RR>mid)update(rt<<1|1,mid+1,R,LL,RR);
push_up(rt);
}
int query(int rt,int L,int R,int LL,int RR)
{
if(LL<=L && RR>=R)
{
return tree[rt];
}
push_down(rt);
int mid=(L+R)>>1,ans=0;
if(LL<=mid) ans=max(ans,query(rt<<1,L,mid,LL,RR));
if(RR>mid) ans=max(ans,query(rt<<1|1,mid+1,R,LL,RR));
return ans;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1; i<=n; ++i)
scanf("%d",&v[i]);
for(int i=1; i<=n; ++i)
{
pre[i]=mark[v[i]]+1;
mark[v[i]]=i;
}
for(int i=1; i<=k; ++i)
{
build(1,1,n,i);
for(int j=1; j<=n; ++j)
{
update(1,1,n,pre[j],j);
dp[j][i]=query(1,1,n,1,j);
}
}
printf("%d\n",dp[n][k]);
return 0;
}

CodeForces833 B. The Bakery 线段树维护dp的更多相关文章

  1. Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)

    题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...

  2. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  3. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

  4. CF833B The Bakery 线段树,DP

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

  5. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  6. 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】

    题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...

  7. 2019牛客暑期多校训练营(第二场)E 线段树维护dp转移矩阵

    题意 给一个\(n\times m\)的01矩阵,1代表有墙,否则没有,每一步可以从\(b[i][j]\)走到\(b[i+1][j]\),\(b[i][j-1]\),\(b[i][j+1]\),有两种 ...

  8. Codeforces750E. New Year and Old Subsequence (线段树维护DP)

    题意:长为2e5的数字串 每次询问一个区间 求删掉最少几个字符使得区间有2017子序列 没有2016子序列 不合法输出-1 题解:dp i,p(0-4)表示第i个数匹配到2017的p位置删掉的最少数 ...

  9. hdu4719 Oh My Holy FFF 线段树维护dp

    题意:给你一个长度为n的数组v,你需要把这个数组分成很多段,你需要保证每一段的长度不能超过k我们设一共有m段,每一段右边界那个数为bi那么我们要使得sum(bi*bi-b(i-1))最大 (1< ...

随机推荐

  1. TCP/IP五层模型-传输层-TCP协议

    ​1.定义:TCP是一种面向连接.可靠的.基于字节流的传输控制协议. 2.应用场景:TCP为可靠传输,适合对数据完整性要求高,对延时不敏感的场景,比如邮件. 3.TCP报文:①TCP报文格式: ②TC ...

  2. Docker Harbor 高可用 1.7.5版本(七)

    环境说明: node1 10.10.5.135 仓库 1 node2 10.10.5.136 仓库 2 node3 10.10.5.137 客户端 实验内容: Harbor 可以在两台主机之间相互同步 ...

  3. appium元素识别方式实战

    github代码::  https://github.com/w550856163/App_Demo.git  tag: V1.1 Appium Inspector定位工具界面介绍:  Selecte ...

  4. (十八)configparser模块

    configparser模块一般是用来处理配置文件的,如: [DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel ...

  5. pidof

    pidof 服务名称,就可以查看到服务占用的进程号

  6. 不要把file,process或者super权限授予管理员以外的账号

    file权限的主要作用是通过select ....into outfile 写到服务器上具有写权限的目录下,作为文本格式存放,具有权限的目录也就是启动mysql时的用户权限目录.(没有理解) 可以将有 ...

  7. OLE NumberFormat

    设置单元格的数字格式, $3.00 想搞出这样的格式,在VBA里的格式定义如下 $#,##0.00;-$#,##0.00 可是在abap里,就是不行.最后尝试了很多次,原来在在$前面加\变成\$#,# ...

  8. 1V转3.3V稳压供电的芯片电路图

    1V转3.3V供电是简单的,仅需要一个芯片和三个外围元件即可组成这样的一个1V转3.3V的电路图和升压电路了.可以持续稳定地供电3.3V给模块或者MCU灯电路.让后端工作稳定,同时也能控制电路的功耗. ...

  9. Django-初阶实例

    调用本地css文件的方法 setting.py里面的内容 import os # Build paths inside the project like this: os.path.join(BASE ...

  10. 参数模型检验过滤器 .NetCore版

    最近学习 .NETCore3.1,发现过滤器的命名空间有变化. 除此以外一些方法的名称和使用方式也有变动,正好重写一下. 过滤器的命名空间的变化 原先:System.Web.Http.Filters; ...