2021.08.01 P4311 数字序列(左偏树)

[P4331 BalticOI 2004]Sequence 数字序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

重点:

1.对于左偏树的应用

2.好好复习一下高中数学必修三

题意:

给定一个整数序列a_1, a_2, ··· , a_n,求出一个递增序列b_1 < b_2 < ··· < b_n,使得序列a_i和b_i的各项之差的绝对值之和|a_1 - b_1| + |a_2 - b_2| + ··· + |a_n - b_n|最小。

分析:

当求一个数x,使得a[1],a[2]…,a[n]最小,这个数为这n个数的中位数。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std; const int N=1e6+10;
typedef long long ll;
int n,top,array[N],ansi[N],vis[N],fa[N];
ll ans;
struct node{
ll val;
int rs,ls,rt,size;
}ai[N];
struct nodei{
ll val;
int ls,rs,dis;
}a[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(array[x]==array[y]?x>y:array[x]<array[y])swap(x,y);
//既然要求递增,那肯定是大根堆
//而且要求在尽可能早的位置元素尽可能的小,如果合并,肯定从后开始删除对顶元素
a[x].rs=merge(a[x].rs,y);
if(a[a[x].ls].dis<a[a[x].rs].dis)swap(a[x].ls,a[x].rs);
fa[x]=fa[a[x].ls]=fa[a[x].rs]=x;
a[x].dis=a[a[x].rs].dis+1;
return x;
}
void pop(int x){
vis[x]=1;
fa[a[x].ls]=a[x].ls;fa[a[x].rs]=a[x].rs;
fa[x]=merge(a[x].ls,a[x].rs);
a[x].ls=a[x].rs=a[x].dis=0;
} int main(){
n=read();
for(int i=1;i<=n;i++){
a[i].val=array[i]=read()-i;fa[i]=i;
//ansi[i]=1;
}
a[0].dis=-1;
/*for(int i=1;i<n;i++){
int x=find(i);
fa[x]=merge(x,i+1);
}
for(int i=1;i<=n;i++)
cout<<i<<" ls "<<a[i].ls<<" rs "<<a[i].rs<<" val "<<a[i].val<<" id "<<a[i].id<<" dis "<<a[i].dis<<endl;
cout<<endl;*/
//每一个x位置的最小值是包含i的这一堆中的最小值
// 尝试找最长上升子序列
/*for(int i=1;i<=n;i++){
for(int j=1;j<i;j++)if(ai[j]<ai[i])ansi[i]=max(ansi[i],ansi[j]+1);
}
for(int i=1;i<=n;i++)cout<<ansi[i]<<" ";
cout<<endl<<endl;*/
//没用
//运用中位数知识,中位数必须递增,否则和前一个小区间合并
for(int i=1;i<=n;i++){
++top;
ai[top].ls=ai[top].rs=ai[top].rt=i;ai[top].size=1;
ai[top].val=array[i];
while(top>1&&ai[top].val<ai[top-1].val){
//合并区间
--top;
ai[top].rt=merge(ai[top].rt,ai[top+1].rt);
ai[top].size+=ai[top+1].size;
ai[top].rs=ai[top+1].rs;
while(ai[top].size*2>ai[top].rs-ai[top].ls+2){//严格的中位数
//size>(rs-ls+1)/2->size*2>rs-ls+1
//当rs-ls+1为偶数时,取偏后的数为中位数
//当rs-ls+1为奇数时,向上取整
--ai[top].size;
ai[top].rt=merge(a[ai[top].rt].ls,a[ai[top].rt].rs);
//简易版pop:不断删去堆顶的中位数
}
ai[top].val=array[ai[top].rt];
}
/*for(int j=1;j<=n;j++)
cout<<j<<" ls "<<a[j].ls<<" rs "<<a[j].rs<<" dis "<<a[j].dis<<" val "<<a[j].val<<endl;
cout<<endl<<endl;*/
}
/*for(int i=1;i<=top;i++)
cout<<i<<" ls "<<ai[i].ls<<" rs "<<ai[i].rs<<" rt "<<ai[i].rt<<" val "<<ai[i].val<<endl;
cout<<endl;*/
for(int i=1;i<=top;i++)for(int j=ai[i].ls;j<=ai[i].rs;j++){
ansi[j]=ai[i].val;
ans+=abs(ai[i].val-array[j]);
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)cout<<ansi[i]+i<<" ";
return 0;
}

2021.08.01 P4311 数字序列(左偏树)的更多相关文章

  1. 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]

    题目传送门 数字序列 题目描述 给定一个整数序列 a1​,a2​,⋅⋅⋅,an​ ,求出一个递增序列 b1​<b2​<⋅⋅⋅<bn​ ,使得序列 ai​ 和 bi​ 的各项之差的绝对 ...

  2. 洛谷$P4331\ [BOI2004]\ Sequence$ 数字序列 左偏树

    正解:左偏树 解题报告: 传送门$QwQ$ 开始看到的时候$jio$得长得很像之前做的一个$dp$,,, 但是$dp$那题是说不严格这里是严格? 不难想到我们可以让$a_{i},b_{i}$同时减去$ ...

  3. Luogu P4331 [BOI2004]Sequence 数字序列 (左偏树论文题)

    清晰明了%%% Fairycastle的博客 个人习惯把size什么的存在左偏树结点内,这样在外面好写,在里面就是模板(只用修改update). 可以对比一下代码(好像也差不多-) MY CODE # ...

  4. 2021.08.01 P3377 左偏树模板

    2021.08.01 P3377 左偏树模板 P3377 [模板]左偏树(可并堆) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<iostream> ...

  5. 黄源河《左偏树的应用》——数字序列(Baltic 2004)

    这道题哪里都找不到. [问题描述] 给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| ...

  6. [BOI2004]Sequence 数字序列(左偏树)

    PS:参考了黄源河的论文<左偏树的特点及其应用> 题目描述:给定一个整数序列\(a_1, a_2, - , a_n\),求一个递增序列\(b_1 < b_2 < - < ...

  7. 2021.08.01 P4359 伪光滑数(二叉堆)

    2021.08.01 P4359 伪光滑数(二叉堆) [P4359 CQOI2016]伪光滑数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 若一个大于 11 的整数 MM ...

  8. 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)

    1367: [Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Ou ...

  9. 【左偏树+贪心】BZOJ1367-[Baltic2004]sequence

    [题目大意] 给定一个序列t1,t2,...,tn ,求一个递增序列z1<z2<...<zn , 使得R=|t1−z1|+|t2−z2|+...+|tn−zn| 的值最小.本题中,我 ...

随机推荐

  1. 7月2日 Django 生成验证码、

    html页面里 {# 验证码 #} <div class="form-group " id="v-code-wrapper"> <label ...

  2. 4月2日 python学习总结

    昨天内容回顾: 1.迭代器 可迭代对象: 只要内置有__iter__方法的都是可迭代的对象 既有__iter__,又有__next__方法 调用__iter__方法==>得到内置的迭代器对象 调 ...

  3. ctf之计算器

    题目信息如下: 打开环境,发现是一道简单的计算题 只能输入一位数字 F12查看源码发现作者将最大长度设置为1,我们将最大长度修改了即可 输入答案即可得到flag

  4. mysql备份灵活恢复

    mysql备份灵活恢复 服务上线遇到一个问题,开始操作前做了全库备份,但是没有做要操作的库备份,如果操作过程出现失败情况需要回退时,直接用全备文件做全库恢复很不妥当. 通过mysql的全备份文件,可以 ...

  5. 百度地图Api使用常见问题

    引用 百度地图API文档 百度地图使用文档 使用 LocalSearch 控件搜索出来的Marker无法点击的问题或者导致第一个Marker标注的信息框关闭后Label消失 解决方法就是使用 onMa ...

  6. oracle.i18n.text.convert.CharacterConverterOGS.getInstance(I)Loracle/i18n/text/converter/CharacterConver;

    看看项目是不是同时包含ojdbc系列jar包和nls_charset12.jar包.如果同时包含,则删除nls_charset12.jar.因为低版本的nls_charset12和ojdbc包冲突.

  7. 面试问题之C++语言:面向对象的三大特性

    转载于:https://www.cnblogs.com/BEN-LK/p/10720249.html 面向对象的三大特性:封装.继承.多态 封装:就是把客观事物封装成抽象的类,并且类可以把自己的数据和 ...

  8. 转:为什么数据库选B-tree或B+tree而不是二叉树作为索引结构

    转载至:https://blog.csdn.net/sinat_27602945/article/details/80118362 B-Tree就是我们常说的B树,一定不要读成B减树,否则就很丢人了. ...

  9. Python - 字符串基础知识

  10. 10.Flink实时项目之订单维度表关联

    1. 维度查询 在上一篇中,我们已经把订单和订单明细表join完,本文将关联订单的其他维度数据,维度关联实际上就是在流中查询存储在 hbase 中的数据表.但是即使通过主键的方式查询,hbase 速度 ...