【STSRM12】夏令营(分治决策单调+主席树)
【题意】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】夏令营(分治决策单调+主席树)的更多相关文章
- SRM12 T2夏令营(分治优化DP+主席树 (已更新NKlogN)/ 线段树优化DP)
先写出朴素的DP方程f[i][j]=f[k][j-1]+h[k+1][i] {k<i}(h表示[k+1,j]有几个不同的数) 显然时间空间复杂度都无法承受 仔细想想可以发现对于一个点 i ...
- zoj 2112 单点修改的主席树(树状数组套主席树)
题目大意: 区间第k大问题+单点修改 基本思路: 这个题有用整体二分,cdq分治,还有主席树+平衡树的,还有就是主席树+树状数组. 我采用的是b站电子科大大佬的主席树写法,尤其喜欢他的离散化方法,所以 ...
- BZOJ 4367 [IOI2014]holiday (决策单调DP+主席树+分治)
题目大意:略 题目传送门 神题,不写长题解简直是浪费了这道题 贪心 考虑从0节点出发的情况,显然一直往前走不回头才是最优策略 如果起点是在中间某个节点$s$,容易想到,如果既要游览$s$左边的某些景点 ...
- 【学术篇】CF833B TheBakery 分治dp+主席树
题目の传送门~ 题目大意: 将\(n\)个蛋糕分成恰好\(k\)份, 求每份中包含的蛋糕的种类数之和的最大值. 这题有两种做法. 第一种是线段树优化dp, 我还没有考虑. 另一种就是分治+主席树. 然 ...
- bzoj 4826: [Hnoi2017]影魔 [主席树 单调栈]
4826: [Hnoi2017]影魔 题意:一个排列,点对\((i,j)\),\(p=max(i+1,j-1)\),若\(p<a_i,a_j\)贡献p1,若\(p\)在\(a_1,a_2\)之间 ...
- Luogu4755 Beautiful Pair 最值分治、主席树
传送门 整天做一些模板题感觉药丸 设\(val_i\)表示第\(i\)个位置的值 看到区间最大值考虑最值分治.对于当前的区间\([l,r]\),找到区间最大值\(mid\),递归\([l,mid-1] ...
- [IOI2014]holiday假期(分治+主席树)
题目描述 健佳正在制定下个假期去台湾的游玩计划.在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点.在台湾共有n个城市,它们全部位于一条高速公路上.这些城市连续地编号为0到n-1.对于城市i( ...
- CF868 F. Yet Another Minimization Problem 决策单调优化 分治
目录 题目链接 题解 代码 题目链接 CF868F. Yet Another Minimization Problem 题解 \(f_{i,j}=\min\limits_{k=1}^{i}\{f_{k ...
- 洛谷P3248 树 [HNOI2016] 主席树+倍增+分治
正解:主席树+倍增+分治 解题报告: 传送门! 首先看到这题会想到之前考过的这题 但是那题其实简单一些,,,因为那题只要用个分治+预处理就好,只是有点儿思维难度而已 这题就不一样,因为它说了是按照原树 ...
随机推荐
- Android AppWidget偶尔无响应原因及解决办法
Android AppWidget偶尔会出现无响应问题,如按钮点击失效,数据不更新等等. 测试后发现,一般出现在手机用清理工具(或系统自己)清理后发生,或手机重启后发生. 目前经过测试,找到的办法是把 ...
- CWindowWnd类源码分析
CWindowWnd代码在UIBase.h和UIBase.cpp文件里.主要实现的是一个基本窗口的创建与消息处理. 相关代码: 头文件: class UILIB_API CWindowWnd { pu ...
- 【廖雪峰老师python教程】——模块
使用模块 任何模块代码的第一个字符串都被视为模块的文档注释: 使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名: 当我们在命令行运行模块文件时,Python解释器把 ...
- spring boot 线程池配置
1.配置类 package cn.com.bonc.util; import java.util.concurrent.Executor; import java.util.concurrent.Th ...
- C# 结构类型与类的区别
结构类型是值类型:类是引用类型: 内存位置不同,结构类型在应用程序的堆栈中:类对象在托管中: 是否改变源对象
- python之pyquery库
如果熟悉jquery,那么使用pyquery进行网页信息提取将会是非常方便的,因为语法都是一样的 1.字符串初始化 2.url和文件初始化 3.CSS选择器 4.子元素 5.父元素 6.兄弟节点 7. ...
- DFS(2)——hdu1241Oil Deposits
一.题目回顾 题目链接:Oil Deposits 题意:给你一块网格,网格被分为面积相等的地块,这些地块中标记'@'的是油田,标记'*'的不是油田.已知一块油田与它上下左右以及对角线的油田同属一片油区 ...
- Packet filtering with Linux & NAT
http://www.linuxfocus.org/ChineseGB/May2003/article289.shtml Gateway, Proxy-Arp 和 Ethernet Bridge ? ...
- bootstrap和elementUI真的会冲突
前两天,做了一个支持markdown的功能: http://www.cnblogs.com/XHappyness/p/8097756.html 后面发现预览效果某些标签需要bootstrap的支持才能 ...
- Configuring Dojo with dojoConfig - The Dojo Toolkit
转载自Dojo官网 Configuring Dojo with dojoConfig The dojoConfig object (formerly djConfig) allows you to s ...