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. 通过blacklist来禁用驱动

    blacklist黑名单 我们在linux中安装驱动,有时会遇到受限或冲突,通常解决方式都是要修改blacklist.conf.对内核模块来说,黑名单是指禁止某个模块装入的机制 在 /etc/modp ...

  2. java中对集合操作的易错点01

    今天用for循环遍历集合,对集合中满足条件的元素进行remove操作报错:ConcurrentModificationException 所以,在遍历集合进行增.删操作时,要使用迭代器的方式 publ ...

  3. Java中获取applicationcontext(应用上下文)

    package com.wl.iwbservice.util; import org.springframework.beans.BeansException; import org.springfr ...

  4. GoldenEye

    靶机准备 将靶机ova文件导入虚拟机,并将网络模式设置为NAT 先进行ip扫描 netdiscover -r 192.168.164.0/24 kali:192.168.164.137 渗透测试 扫描 ...

  5. mock axios vue的数据传递关系

    最近有一个项目要快速出一个前端demo,选择了vue-element框架(虽然其实很想用react,但是为了求快) 本人的基础只有初级的html/css/js知识,和python后端的一些简单工作,和 ...

  6. JVM中的常量池

    在Java的内存分配中,总共3种常量池: ref:https://blog.csdn.net/zm13007310400/article/details/77534349 1.字符串常量池(Strin ...

  7. SynchronizedMap 和 ConcurrentHashMap 有什么区别?

    SynchronizedMap 一次锁住整张表来保证线程安全,所以每次只能有一个线程来 访为 map. ConcurrentHashMap 使用分段锁来保证在多线程下的性能. ConcurrentHa ...

  8. Java 中怎么打印数组?

    你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法来打印数组.由 于数组没有实现 toString() 方法,所以如果将数组传递给 System.ou ...

  9. CopyOnWriteArrayList 可以用于什么应用场景?

    CopyOnWriteArrayList(免锁容器)的好处之一是当多个迭代器同时遍历和修改这 个列表时,不会抛出 ConcurrentModificationException.在 CopyOnWri ...

  10. memcached 如何实现冗余机制?

    不实现!我们对这个问题感到很惊讶.Memcached 应该是应用的缓存层.它的设 计本身就不带有任何冗余机制.如果一个 memcached 节点失去了所有数据,您 应该可以从数据源(比如数据库)再次获 ...