【题意】n个数字分成k段,每一段的价值是段内不同数字的个数,求最大价值。n<=35000,k<=50。

【算法】分治决策单调+主席树(可持久化线段树)

【题解】

f[i][j]表示前i天分成j段的最大价值。

f[i][j]=max(f[k][j-1]+work(k+1,i)),j-1<=k<i。

首先打表发现有决策单调性(把j提到第一维)。

然后有经典写法:主席树维护区间不同数字个数。

那么根据决策单调性进行分治,在每次l,r(mid=l+r>>1)从L,R中转移时,用主席树求R~mid,然后从右到左每个位置若nex>mid则sum++,统计答案。

这样每个分治区域使用一次主席树,共有至多4*n次分治(类比线段树节点数),这样主席树的复杂度和分治并列,复杂度可以满足。

复杂度O(k*n log n+4*n log n)。

主席树空间注意不要自信预估……开大两倍。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
const int maxn=,maxk=;
int f[][maxn],sz,tot,root[maxn],nex[maxn],last[maxn],x,n,kind,a[maxn],b[maxn],c[maxn];
struct tree{int l,r,sum;}t[]; inline int min(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return a>b?a:b;}
int read()
{
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
void build(int l,int r,int &x,int y,int c){
x=++sz;
t[x]=t[y];t[x].sum++;
if(l==r)return;
int mid=(l+r)>>;
if(c<=mid)build(l,mid,t[x].l,t[y].l,c);
else build(mid+,r,t[x].r,t[y].r,c);
}
int ask(int l,int r,int x,int c){
if(x==)return ;
if(r<=c)return t[x].sum;
int mid=(l+r)>>,ans=;
if(c>mid)ans+=ask(mid+,r,t[x].r,c);
ans+=ask(l,mid,t[x].l,c);
return ans;
}
int calc(int l,int r)
{return ask(,n,root[r],l-)-ask(,n,root[l-],l-);}
void find(int l,int r,int L,int R){
if(l>r||L>R)return;
int mid=(l+r)>>,sum=calc(min(R+,mid),mid);
int wh=;
for(int i=min(R,mid-);i>=L;i--){
if(f[x][mid]<f[-x][i]+sum){
f[x][mid]=f[-x][i]+sum;
wh=i;
}
if(nex[i]>mid)sum++;
}
find(l,mid-,L,wh);
find(mid+,r,wh,R);
}
int main(){
n=read();kind=read();
for(int i=;i<=n;i++)a[i]=read(),b[i]=a[i];
sort(b+,b+n+);tot=n;
tot=unique(b+,b+tot+)-b-;
for(int i=;i<=n;i++)a[i]=lower_bound(b+,b+tot+,a[i])-b;
for(int i=;i<=n;i++){
last[i]=c[a[i]];
c[a[i]]=i;
}
memset(c,,sizeof(c));
for(int i=n;i>=;i--){
nex[i]=c[a[i]]==?n+:c[a[i]];
c[a[i]]=i;
}
for(int i=;i<=n;i++)build(,n,root[i],root[i-],last[i]);
x=;
memset(f[x],-,sizeof(f[x]));
f[x][]=;
for(int j=;j<=kind;j++){
x=-x;
memset(f[x],-,sizeof(f[x]));
find(,n,,n);
}
printf("%d",f[x][n]);
return ;
}

另一种写法:线段树

DP的瓶颈主要在于work(k+1,i)部分,否则就可以线段树查询max了。

对于已有的k~i-1,加入新的数字i(i上一次出现的位置为p),只有左端点p+1及之后的点才会+1,这就是个区间加操作。

那么每次区间加和区间查,j作为第一维换的时候重建树。

【STSRM12】夏令营(分治决策单调+主席树)的更多相关文章

  1. SRM12 T2夏令营(分治优化DP+主席树 (已更新NKlogN)/ 线段树优化DP)

     先写出朴素的DP方程f[i][j]=f[k][j-1]+h[k+1][i] {k<i}(h表示[k+1,j]有几个不同的数)  显然时间空间复杂度都无法承受   仔细想想可以发现对于一个点 i ...

  2. zoj 2112 单点修改的主席树(树状数组套主席树)

    题目大意: 区间第k大问题+单点修改 基本思路: 这个题有用整体二分,cdq分治,还有主席树+平衡树的,还有就是主席树+树状数组. 我采用的是b站电子科大大佬的主席树写法,尤其喜欢他的离散化方法,所以 ...

  3. BZOJ 4367 [IOI2014]holiday (决策单调DP+主席树+分治)

    题目大意:略 题目传送门 神题,不写长题解简直是浪费了这道题 贪心 考虑从0节点出发的情况,显然一直往前走不回头才是最优策略 如果起点是在中间某个节点$s$,容易想到,如果既要游览$s$左边的某些景点 ...

  4. 【学术篇】CF833B TheBakery 分治dp+主席树

    题目の传送门~ 题目大意: 将\(n\)个蛋糕分成恰好\(k\)份, 求每份中包含的蛋糕的种类数之和的最大值. 这题有两种做法. 第一种是线段树优化dp, 我还没有考虑. 另一种就是分治+主席树. 然 ...

  5. bzoj 4826: [Hnoi2017]影魔 [主席树 单调栈]

    4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...

  6. Luogu4755 Beautiful Pair 最值分治、主席树

    传送门 整天做一些模板题感觉药丸 设\(val_i\)表示第\(i\)个位置的值 看到区间最大值考虑最值分治.对于当前的区间\([l,r]\),找到区间最大值\(mid\),递归\([l,mid-1] ...

  7. [IOI2014]holiday假期(分治+主席树)

    题目描述 健佳正在制定下个假期去台湾的游玩计划.在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点.在台湾共有n个城市,它们全部位于一条高速公路上.这些城市连续地编号为0到n-1.对于城市i( ...

  8. CF868 F. Yet Another Minimization Problem 决策单调优化 分治

    目录 题目链接 题解 代码 题目链接 CF868F. Yet Another Minimization Problem 题解 \(f_{i,j}=\min\limits_{k=1}^{i}\{f_{k ...

  9. 洛谷P3248 树 [HNOI2016] 主席树+倍增+分治

    正解:主席树+倍增+分治 解题报告: 传送门! 首先看到这题会想到之前考过的这题 但是那题其实简单一些,,,因为那题只要用个分治+预处理就好,只是有点儿思维难度而已 这题就不一样,因为它说了是按照原树 ...

随机推荐

  1. 【好帖】 Mark

    1. 管理篇 2. 程序员选择公司的8个标准 3. 实用工具 4. 离职跳槽 5. DBA 6. 做一个网站多少钱? 7. 十大算法 8. 寻求用户评价App的正确方法 9. 工程师忽略的隐形成本 1 ...

  2. 第九篇 Python数据类型之集合

    集合 set 写在最前,必须要会的:1.长度len2.成员运算in和not in3.|合集4.&交集5.-差集6.^对称差集7.==8.父集:>,>= 9.子集:<,< ...

  3. Python 基本文件操作

    文件模式 'r' 读模式 'w' 写模式 (清除掉旧有数据并重新开始) 'a' 追加模式 'b' 二进制模式 '+' 读/写模式 注意: 'b'   : 二进制模式 可添加到其他模式中使用 '+'  ...

  4. CCF-NOIP-2018 提高组(复赛) 模拟试题(七)

    T1 Adjoin [问题描述] 定义一种合法的\(0-1\)串:串中任何一个数字都与\(1\)相邻.例如长度为$ 3 的 0-1 $串中,\(101\)是非法的,因为两边的\(1\)没有相邻的\(1 ...

  5. python 基础篇 15 内置函数和匿名函数

    ------------------------>>>>>>>>>>>>>>>内置函数<<< ...

  6. Floatingip

    浮动IP相关功能点: 模块 功能 描述 备注 FloatingIP 创建浮动IP 指定带宽大小创建单个/多个浮动IP   指定子网.指定IP创建浮动IP   绑定浮动IP,修改带宽 绑定浮动IP到指定 ...

  7. pep8介绍

    pep8介绍: PEP8是针对python代码格式而编订的风格指南,采用一致的编码风格可以令代码更加易懂易读! (1)空白: python中空白会影响代码的含义及其代码的清晰程度 使用space(空格 ...

  8. flask - 1

    from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, Worl ...

  9. Week1 Team Homework #1 from Z.XML-项目选择思路--基于对曾经大作业项目的思考

    这两天试玩了一下去年学长的满分工程<shield star>游戏,再结合了一下他们团队的博客记录,有一种非常牛逼的感觉.具体对于这款游戏的一些思考和看法,毛大神已经说的很好了.因此,这里主 ...

  10. SSH 项目中 使用websocket 实现网页聊天功能

    参考文章  :java使用websocket,并且获取HttpSession,源码分析    http://www.cnblogs.com/zhuxiaojie/p/6238826.html 1.在项 ...