题目链接:http://codeforces.com/contest/834/problem/D

题意:给定一个长度为n的序列和一个k,现在让你把这个序列分成刚好k段,并且k段的贡献之和最大。对于每一段的贡献为该段有多少个不同的数字。

思路:考虑dp, dp[k][i]表示前i个数切k段的答案,那么dp[k][i]=max(dp[k-1][j]+color(j+1,i)) [1<=j<i], [color(l,r)表示区间[l,r]有多少个不同的数字] ,由于第k行的dp值只会影响到k+1行的dp值,所以我们可以把k这一维忽略掉。考虑转移dp[k][i+1],新增加的i+1这个点会影响到[pre[a[i]]+1,i]这段区间+1。

ftiasch的题解

我们在建线段树的时候,树上的结点(结点表示的区间为[l,r])维护的是g[k](即dp[k-1][r-1]),然后就是区间加和区间最大值了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
#include <bitset>
using namespace std;
typedef long long LL;
const int MAXN = + ; int n,k,pre[MAXN],dp[MAXN];
struct Color{
int val,l,r;
}c[MAXN]; //Segment Tree
#define L(x)(x<<1)
#define R(x)(x<<1|1)
struct Node{
int l,r,Lazy,maxval;
Node(int _l=,int _r=,double _val=){
l=_l; r=_r; maxval=_val;
}
}Seg[MAXN*];
void pushUp(int k){
Seg[k].maxval=max(Seg[L(k)].maxval,Seg[R(k)].maxval);
}
void pushDown(int k){
if(Seg[k].Lazy){
Seg[L(k)].Lazy+=Seg[k].Lazy;
Seg[L(k)].maxval+=Seg[k].Lazy;
Seg[R(k)].Lazy+=Seg[k].Lazy;
Seg[R(k)].maxval+=Seg[k].Lazy;
Seg[k].Lazy=;
}
}
void Build(int st,int ed,int k){
Seg[k].l=st; Seg[k].r=ed; Seg[k].Lazy=;
if(st==ed){
Seg[k].maxval=dp[st-];
return;
}
int mid=(st+ed)>>;
Build(st,mid,L(k)); Build(mid+,ed,R(k));
pushUp(k);
}
void Modify(int st,int ed,int k,int val){
if(Seg[k].l==st&&Seg[k].r==ed){
Seg[k].maxval+=val;
Seg[k].Lazy+=val;
return;
}
pushDown(k);
if(Seg[L(k)].r>=ed){
Modify(st,ed,L(k),val);
}else if(Seg[R(k)].l<=st){
Modify(st,ed,R(k),val);
}else{
Modify(st,Seg[L(k)].r,L(k),val); Modify(Seg[R(k)].l,ed,R(k),val);
}
pushUp(k);
}
int Query(int st,int ed,int k){
if(Seg[k].l==st&&Seg[k].r==ed){
return Seg[k].maxval;
}
pushDown(k);
int res;
if(Seg[L(k)].r>=ed){
res=Query(st,ed,L(k));
}else if(Seg[R(k)].l<=st){
res=Query(st,ed,R(k));
}else{
res=max(Query(st,Seg[L(k)].r,L(k)),Query(Seg[R(k)].l,ed,R(k)));
}
pushUp(k);
return res;
}
int main(){
#ifdef kirito
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&k)) {
memset(pre,,sizeof(pre));
for(int i=;i<=n;i++){
scanf("%d",&c[i].val);
c[i].r=i; c[i].l=pre[c[i].val]+; pre[c[i].val]=i;
}
for(int i=;i<=n;i++){
dp[i]=dp[i-]+(c[i].l==?:);
}
for(int j=;j<=k;j++){
Build(,n,);
for(int i=;i<=n;i++){
Modify(c[i].l,c[i].r,,);
dp[i]=Query(,i,);
}
}
printf("%d\n",dp[n]);
}
return ;
}

最新文章

  1. Eclipse中启动tomcat报错java.lang.OutOfMemoryError: PermGen space的解决方法
  2. Swift: 比较Swift中闭包传值、OC中的Block传值
  3. Adding New Functions to MySQL(User-Defined Function Interface UDF、Native Function)
  4. linq小笔记;
  5. 7 天玩转 ASP.NET MVC — 第 6 天
  6. Window 2008 R2 + IIS7.5 + VS2013 错误代码 0x80070002
  7. MVC bundles
  8. 对TextView设置drawable,用setCompoundDrawables方法实现
  9. HTML5 拖拽效果实现
  10. Html 经典布局(三)
  11. 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数
  12. 背景新增属性和css渐变及倒影
  13. BZOJ_2068_[Poi2004]SZP_树形DP
  14. Oracle查看表空间
  15. SVN和Git对比梳理
  16. Office Web Apps安装部署(二)
  17. 用python对txt中文件读取,然后按顺序标号存入excel中
  18. 在.net中修改Webbrowser控件的IE版本
  19. 用LinkedList
  20. Knockout与Require框架同时使用时的visible绑定的问题,造成的影响,以及解决的方法。

热门文章

  1. Bootstrap Table--onEditableSave
  2. Spring MVC过滤器HiddenHttpMethodFilter
  3. Servlet的常见错误
  4. code first System.Data.Entity.Infrastructure.CommitFailedException: An error was reported while committing a database transaction but it could not be determined whether the transaction succeeded
  5. Python 写 ACM 题目的一些技巧
  6. 使用Zabbix通过ILO管理口监控惠普服务器
  7. 二、启动一款app演示
  8. 杂项-桌面应用程序:Windows Live Writer(WLW)
  9. Git+Jenkins配置
  10. Openstack_单元测试工具 tox