CF834D
题目链接:http://codeforces.com/contest/834/problem/D
题目大意:将一个有n个数的数列分成k段,每段的价值为该段中不同数字的个数,求k段的最大总价值。
解题思路:
思路来自叉姐 + GreenGrape
dp + segment trees.
dp不难想到。前 i 个数分成 j 段的最大价值:dp[i][j] = max( dp[i-1][k] + w(k+1,j), i-1 <= k < j). 但其实这样直接去搞的话分分钟TLE。
所以,我们需要使用线段树。详情请看代码,里面有个人的注释,请指教。
AC代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <string>
#include <queue> using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define root 1 , N , 1
const int maxn=+;
int a[maxn],dp[][maxn],last[maxn];
int pre[maxn];
int tree[maxn<<],lazy[maxn<<]; //*****************************************************
//这一部分其实就是走模板
void pushup(int rt){
tree[rt]=max(tree[rt<<],tree[rt<<|]);
}
void pushdown(int rt){
if(lazy[rt]){
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
tree[rt<<]+=lazy[rt];
tree[rt<<|]+=lazy[rt];
lazy[rt]=;
}
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
lazy[rt]+=c;
tree[rt]+=c;
return;
}
pushdown(rt);
int m=(l+r)>>;
if(L<=m) update(L,R,c,lson);
if(m<R) update(L,R,c,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R)
return tree[rt];
pushdown(rt);
int m=(l+r)>>;
int ret=;
if(L<=m) ret=max(ret,query(L,R,lson));
if(m<R) ret=max(ret,query(L,R,rson));
return ret;
}
//******************************************************* int main(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
pre[i]=last[a[i]];//pre[i]记录a[i]上一次出现的位置
last[a[i]]=i;
}
for(int i=;i<=k;i++){
memset(tree,,sizeof(tree));
memset(lazy,,sizeof(lazy));
for(int j=i-;j<=n;j++)
update(j,j,dp[i-][j],,n,);//把线段树各叶子结点的值初始化为dp[i-1][]的值,在dp[i][]这一维度上的操作其实就是在dp[i-1][]的基础上进行的。前面不能忘了把线段树的数据置0。
for(int j=i;j<=n;j++){
//对于以x为结尾(pre[j] <= x <= j-1)的dp[i-1][x],将a[j]作为第 i 段的结尾可以使得dp[i-1][x]对应的dp[i][j]的值+1。
//故此时线段树维护的就是max(dp[i-1][k] + w(k+1,j), i-1 <= k < j)。w(k+1,j)在这个更新的过程中逐次加和累积。实在是精妙无比。
update(pre[j],j-,,,n,);
dp[i][j]=query(,j,,n,);
}
}
int ans=;
for(int j=k;j<=n;j++){
if(dp[k][j]>ans) ans=dp[k][j];
}
printf("%d\n",ans);
return ;
}
CF834D的更多相关文章
- CF834D The Bakery
题目链接:戳我 题意:将一个长度为n的序列分为k段,使得总价值最大.一段区间的价值表示为区间内不同数字的个数 \(n<=35000,k<=50\) 开始想的转移方程是这个样子的--\(dp ...
- cf834D(dp+线段树区间最值,区间更新)
题目链接: http://codeforces.com/contest/834/problem/D 题意: 每个数字代表一种颜色, 一个区间的美丽度为其中颜色的种数, 给出一个有 n 个元素的数组, ...
随机推荐
- 飞机大战-面向对象-pygame
飞机大战 最近学习了python的面向对象,对面向对象的理解不是很深刻. 面向对象是数据和函数的'打包整理',将相关数据和处理数据的方法集中在一个地方,方便使用和管理. 本着学习的目的,在网上找了这个 ...
- Visual Studio Code mac OS 安装 中文简体语言包
先下载中文简体语言包 官网 https://marketplace.visualstudio.com/search?target=VSCode&category=Language%20Pack ...
- mac OS 安装 Eclipse
安装Eclipse前先确认你的Mac上是否已安装Java运行环境.进入终端,输入"java -version",如果返回了java版本号则说明已安装 访问Eclipse官方首页ht ...
- java 设计模式-责任链
责任链设计模式,其实就是处理同一个请求的对象连接成一条链,请求的路径经过这条链,符合要求的就处理这个请求,不符合就接着往下面抛出,直道有人处理这条请求. 业务:比如啊,公司个人请假,三天以下就是主管审 ...
- 数学--数论--HDU-2698 Maximum Multiple(规律)
Given an integer nn, Chiaki would like to find three positive integers xx, yy and zzsuch that: n=x+y ...
- SpringBoot返回JSON日期格式问题
SpringBoot中默认返回的日期格式类似于这样: "birth": 1537407384500 或者是这样: "createTime": "201 ...
- springdata jpa基本注解
Springdata jpa的基本注解 1:@Entity @Entity注解用在实体类声明语句前,说明该Java类为实体类,将映射到指定的数据库表. 2:@Table @Table注解用在当实体类与 ...
- spring内嵌jetty容器,实现main方法启动web项目
Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境.Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布.开发人员可以将 ...
- centos系统克隆
首先保证虚拟机处于关机状态. 1.修改网卡信息 vi /etc/sysconfig/network-scripts/ifcfg-eth0 删除网卡信息HWADDR与UUID信息 修改IPADDR信息为 ...
- Spring Cloud学习 之 Spring Cloud Ribbon 重试机制及超时设置不生效
今天测了一下Ribbon的重试跟超时机制,发现进行的全局超时配置一直不生效,配置如下: ribbon: #单位ms,请求连接的超时时间,默认1000 ConnectTimeout: 500 #单位ms ...