【题意】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. python内置模块[sys,os,os.path,stat]

    python内置模块[sys,os,os.path,stat] 内置模块是python自带功能,在使用内置模块时,需要遵循 先导入在 使用 一.sys 对象 描述 sys.argv 命令行参数获取,返 ...

  2. 了解url

    我对自己知道关于url的编码和解码的一些进行了一下整理. 我们的例子是百度翻译的地址: http://fanyi.baidu.com/translate#en/zh/The%20%22%3F%20ar ...

  3. 关于Vue脚手架写法的问题

    问题描述: main.js import Vue from 'vue' import App from './App' /* eslint-disable no-new */ new Vue({ el ...

  4. Assetbundle1

    AssetBundle运行时加载:来自文件就用CreateFromFile(注意这种方法只能用于standalone程序)这是最快的加载方法也可以来自Memory,用CreateFromMemory( ...

  5. xamdin: 添加小组件报错: render() got an unexpected keyword argument 'renderer'

    查找到 xadmin里面的 dashboard.py文件内render方法,增加一个rdnderer默认参数是None一般路径在 本机虚拟环境\Lib\site-packages\xadmin\vie ...

  6. ADVICE FOR SHORT-TERM MACHINE LEARNING RESEARCH PROJECTS(短期机器学习研究的建议)

    – Tim Rocktäschel, Jakob Foerster and Greg Farquhar, 29/08/2018 Every year we get contacted by stude ...

  7. Python登录小程序

    ------------------------------------------------- 主要实现功能 1.用户输入用户名,在用户名文件中查找对应的用户,若无对应用户名则打印输入错误 2.用 ...

  8. 深度学习anchor的理解

    摘抄与某乎 anchor 让网络学习到的是一种推断的能力.网络不会认为它拿到的这一小块 feature map 具有七十二变的能力,能同时从 9 种不同的 anchor 区域得到.拥有 anchor ...

  9. Nginx+tomcat+redis集群共享session实现负载均衡

    1.nginx是一款轻量级兼备高性能的Http和反向代理服务器.所谓反向代理就是指用户发起访问请求,由代理服务器接受,然后将请求转发给正式服务器,并且将正式服务器处理完的数据返回给客户单,此时代理服务 ...

  10. pta编程(1-8)

    知识点:本次编程运用到的格式 #include<stdio.h> int main(void) { printf(); return 0; } 过程:1-3.没什么问题,就是注意字符的输入 ...