【STSRM12】夏令营
【题意】n个数划分成k段,每段的价值为段内不同数字的数量,求最大总价值
【算法】DP+线段树
【题解】
f[i][j]表示前i个数字划分成j段的最大价值。
f[i][j]=max(f[k][j-1]+value(k+1,j)),j-1<=k<i。
暴力复杂度O(n^3*k),预处理value后复杂度降为O(n^2*k)。
正解考虑加入一个数字i,只能为k+1~i贡献1的价值,其中k为数字i上一次出现的位置。
那么排序预处理上一次出现位置,区间+1用线段树维护,取max用线段树查询,复杂度O(nk*log n)。
注意线段树常数……特别注意手写max。
从头查比从中间查常数小。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
struct tree{int l,r,ms,delta;}t[maxn*];
struct cyc{int num,ord;}b[maxn];
bool cmp(cyc a,cyc b){return a.num<b.num||(a.num==b.num&&a.ord<b.ord);}
int f[maxn],n,kind,a[maxn],c[maxn];
void pushup(int k){t[k].ms=max(t[k<<].ms,t[k<<|].ms);}
void pushdown(int k){
if(t[k].delta){
t[k<<].delta+=t[k].delta;
t[k<<].ms+=t[k].delta;
t[k<<|].delta+=t[k].delta;
t[k<<|].ms+=t[k].delta;
t[k].delta=;
}
}
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
if(l==r){t[k].ms=f[l];t[k].delta=;}
else{
int mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
pushup(k);
t[k].delta=;
}
}
void insert(int k,int l,int r,int x){
if(l<=t[k].l&&t[k].r<=r){t[k].delta+=x;t[k].ms+=x;}
else{
pushdown(k);
int mid=(t[k].l+t[k].r)>>;
if(l<=mid)insert(k<<,l,r,x);
if(r>mid)insert(k<<|,l,r,x);
pushup(k);
}
}
int query(int k,int l,int r){
if(l<=t[k].l&&t[k].r<=r)return t[k].ms;
else{
pushdown(k);
int mid=(t[k].l+t[k].r)>>;
int ans=;
if(l<=mid)ans=query(k<<,l,r);
if(r>mid)ans=max(ans,query(k<<|,l,r));
return ans;
}
}
int main(){
scanf("%d%d",&n,&kind);
for(int i=;i<=n;i++){scanf("%d",&a[i]);b[i].num=a[i];b[i].ord=i;}
sort(b+,b+n+,cmp);
for(int i=;i<=n;i++)if(b[i].num==b[i-].num)c[b[i].ord]=b[i-].ord;
build(,,n);
for(int j=;j<=kind;j++){
for(int i=;i<=n;i++){
insert(,c[i],i-,);
f[i]=query(,,i-);
}
build(,,n);
}
printf("%d",f[n]);
return ;
}
暴力AC法:打表容易发现具有决策单调性,原因在于加入i时已知i-1的决策点j比左边优,加入i后对i上一次出现的位置到i有贡献,如果左边有贡献则j一定有贡献,所以决策点k>=j。
决策单调性可以用分支决策维护,复杂度O(n^2*k*log n)。
瓶颈在快速求区间数字个数,用主席树维护,复杂度O(nk*log n)。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
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;
}
/*------------------------------------------------------------*/
const int inf=0x3f3f3f3f,maxn=; int n,kind,f[][maxn],a[maxn],x,dfsnum=,b[maxn];
bool c[maxn];
int work(int x,int y){
dfsnum++;
int ans=;
for(int i=x;i<=y;i++)if(b[a[i]]!=dfsnum){
b[a[i]]=dfsnum;
ans++;
}
return ans;
}
void find(int l,int r,int L,int R)
{
if(l>r||L>R)return;
int mid=(l+r)>>;
int w,v=-inf+;
for(int i=L;i<=R&&i<mid;i++){
if(f[-x][i]+work(i+,mid)>v){
v=f[-x][i]+work(i+,mid);
w=i;
}
}
f[x][mid]=v;
find(l,mid-,L,w);
find(mid+,r,w,R);
}
int main()
{
scanf("%d%d",&n,&kind);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
x=;
for(int j=;j<=kind;j++){
x=-x;
f[x][]=-inf;
find(,n,,n-);
}
printf("%d",f[x][n]);
return ;
}
O(n^2*k*log n)
【STSRM12】夏令营的更多相关文章
- 【STSRM12】夏令营(分治决策单调+主席树)
[题意]n个数字分成k段,每一段的价值是段内不同数字的个数,求最大价值.n<=35000,k<=50. [算法]分治决策单调+主席树(可持久化线段树) [题解] f[i][j]表示前i天分 ...
- BUAA & ICT 夏令营之旅
我还只有二十几岁,总应该相信点什么吧. ================================ 7.10午后坐火车赶到北京.一路上火车行驶在茫茫云海里.车窗外的世界是这样子的:一片广袤的原野 ...
- Thu夏令营 总结
感觉这次thu夏令营简直就是爆RP啊 竟然签了无条件本一 [Waring]RP已空 话说这次考试设定 竟然是下午两点开始考试 考到五点- - 导致中午必须午睡 宾馆里清华也不近 按原本试机安排到12点 ...
- FZYZOJ-1578 [NOIP福建夏令营]数列分段
P1578 -- [NOIP福建夏令营]数列分段 时间限制:1000MS 内存限制:131072KB 状态:Accepted 标签: 二分 无 无 Descripti ...
- 值得赞扬的尝试与进步——CSDN开源夏令营第一印象
注:写这篇文章时我并未參加CSDN开源夏令营,也不确定是否会參加以及是否能參加上. 欣闻CSDN举办了"CSDN开源夏令营"活动.第一感觉是CSDN作为活动的组织者是很值得称赞的. ...
- 夏令营讲课内容整理 Day 7.
Day7是夏令营的最后一天,这一天主要讲了骗分技巧和往年经典的一些NOIP试题以及比赛策略. 这天有个小插曲,上午的day7T3是一道和树有关的题,我是想破脑袋也想不出来,正解写不出来就写暴力吧,暴力 ...
- 夏令营提高班上午上机测试 Day 3 解题报告
今天的题的确水.T3还是一道NOIP原题. 嘛,多刷点水题也不是什么坏事嘛. 说来也快,夏令营结束了整一星期了呢.大家也都回到了日常的暑假生活呢. 今天学业水平测试出成绩了...嗯结果还算满意呢,至少 ...
- 夏令营提高班上午上机测试 Day 2 解题报告
那一天,日照一中夏令营数据结构提高班的同学们终于想起了,被Day2上午的三道题支配的恐惧…… 是的..这一天的题有点难想.. 本来打算前天写这篇随笔,然而前天在机房和同学打luogu月赛…… 昨天 ...
- 浴谷夏令营例题Codeforces827DBest Edge Weight(三个愿望,一次满足~(大雾
这题在浴谷夏令营wyx在讲的最小生成树的时候提到过,但并没有细讲怎么写... 这题可以用三种写法写,虽然只有两种能过...(倍增/倍增+并查集/树链剖分 先跑出最小生成树,分类讨论,在MST上的边,考 ...
随机推荐
- How to find your web part
When we deploy a web part, we can find it on any pages through the follow steps: Firstly, ...
- qt 编译unresolved external symbol的错误解决
题外问题:.rc文件报错,里面引用的.h文件打不开. 方法:rc文件移除,然后重新添加就可以: unresolved external symbol的原因: 1.没有添加编译生成的moc文件,添加对应 ...
- fiddler抓包-简单易操作(一)
1.下载fiddler 可以到fiddler官网去下,网址:https://www.telerik.com/download/fiddler 下载完成后,安装即可. 2.运行fiddler,进入fid ...
- GraphSAGE 代码解析(四) - models.py
原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(一) - unsupervised_train.py GraphSAGE 代码解析(二) - layers.py ...
- Go基础篇【第2篇】: 内置库模块 fmt
fmt官方文档说明:https://studygolang.com/pkgdoc import "fmt" mt包实现了类似C语言printf和scanf的格式化I/O.格式化动作 ...
- NO8——排序
//sort #include<algorithm> bool cmp(const int a,const int b) { return a>b;//降序排列 } //qsort ...
- 【iOS开发】动态添加子视图 UIView 的正确方法
很多时候哥比较喜欢用代码添加视图,特别是要同时加很多UIView时,而且跟 xib 比起来代码更容易管理,在多人的项目中代码不容易 conflict. 但小牛哥最近发现很多新人都不太清楚正确的使用方法 ...
- 对TDD的实践感悟
文章:我的TDD实践:可测试性驱动开发(上) 文章表达的思想是,达到一个目的并非只有一种套路,作者用写代码时,时刻考虑代码的可测试性,来推动项目的合理开发.
- Xcode & swift
swift-apps swift 2018 apps Xcode Swift Playground https://developer.apple.com/download/ https://deve ...
- iBatis的基本使用
项目结构: 依赖jar: 数据库依赖: CREATE TABLE `person` ( `id` ) NOT NULL AUTO_INCREMENT, `name` ) NOT NULL, PRIMA ...