【题意】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. (原)一段看似美丽的for循环,背后又隐藏着什么

    之前很长一段时间,潜心修炼汇编,专门装了一个dos7,慢慢玩到win32汇编,再到linux的AT&A汇编,尝试写mbr的时候期间好几次把centos弄的开不了机,又莫名其妙的修好了,如今最大 ...

  2. cachel-control

    nodejs: res.set('Cache-Control', 'public, max-age=31557600'); express全局设置:       app.use(express.sta ...

  3. Appium如何获取appPackage和appActivity

    基本概念: appPackage:简单来说是App开发者提供的名称. appActivity:简单来说是App提供的各种不同的功能.每个程序都有个MainActivity,就是打开程序时显示在屏幕的活 ...

  4. 远程连接云主机MySql数据库

    笔者最近在学习MySql数据库,试着远程连接阿里云主机数据库.在连接过程中遇到不少麻烦,这里总结一下过程中遇到的问题. 基本前提 先在本地电脑和远程主机上安装MySql数据库,保证数据库服务启动. 云 ...

  5. Servlet入门(2)

    1.url_pattern匹配模式 2.servlet生命周期 3.servlet线程问题 一.url_pattern 1.定义: 当浏览器发起一个url请求后,该请求发送到servlet容器的时候, ...

  6. chromium源码阅读

    linux下chromium的入口函数在文件:src/chrome/app/chrome_exe_main_aura.cc 中 int main(int argc, const char** argv ...

  7. Spring Boot学习(二):配置文件

    目录 前言 方式1:通过配置绑定对象的方式 方式2:@Value("${blog.author}")的形式获取属性值 相关说明 注解@Value的说明 参考 前言 Spring B ...

  8. C语言分支/顺序作业总结

    总结 1.1 基本要求(1分) 按时交 - 有分 未交 - 0分 迟交一周以上 - 倒扣本次作业分数 抄袭 - 0分 博客作业格式不规范,没有用Markdown语法 -扣分 泛泛而谈(最多七分) 1. ...

  9. ob_flush()和flush()的区别

    最近写定时任务,遇到ob_flush()和flush()混淆的问题... ob_flush/flush在手册中的描述, 都是刷新输出缓冲区, 并且还需要配套使用, 所以会导致很多人迷惑- 其实, 他们 ...

  10. 习题:就是干(DP)

    洛谷2301 题目描述 眼看着老师大军浩浩荡荡的向机房前进.LOI 的同学们决定动用自己的力量来保卫他们的好朋友loidc.现在每个人都要挑选自己的武器——两根木棍.一根用做远距离投掷,另一根用做近距 ...