2021.08.01 P4311 数字序列(左偏树)
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 数字序列(左偏树)的更多相关文章
- 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]
题目传送门 数字序列 题目描述 给定一个整数序列 a1,a2,⋅⋅⋅,an ,求出一个递增序列 b1<b2<⋅⋅⋅<bn ,使得序列 ai 和 bi 的各项之差的绝对 ...
- 洛谷$P4331\ [BOI2004]\ Sequence$ 数字序列 左偏树
正解:左偏树 解题报告: 传送门$QwQ$ 开始看到的时候$jio$得长得很像之前做的一个$dp$,,, 但是$dp$那题是说不严格这里是严格? 不难想到我们可以让$a_{i},b_{i}$同时减去$ ...
- Luogu P4331 [BOI2004]Sequence 数字序列 (左偏树论文题)
清晰明了%%% Fairycastle的博客 个人习惯把size什么的存在左偏树结点内,这样在外面好写,在里面就是模板(只用修改update). 可以对比一下代码(好像也差不多-) MY CODE # ...
- 2021.08.01 P3377 左偏树模板
2021.08.01 P3377 左偏树模板 P3377 [模板]左偏树(可并堆) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<iostream> ...
- 黄源河《左偏树的应用》——数字序列(Baltic 2004)
这道题哪里都找不到. [问题描述] 给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| ...
- [BOI2004]Sequence 数字序列(左偏树)
PS:参考了黄源河的论文<左偏树的特点及其应用> 题目描述:给定一个整数序列\(a_1, a_2, - , a_n\),求一个递增序列\(b_1 < b_2 < - < ...
- 2021.08.01 P4359 伪光滑数(二叉堆)
2021.08.01 P4359 伪光滑数(二叉堆) [P4359 CQOI2016]伪光滑数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 若一个大于 11 的整数 MM ...
- 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)
1367: [Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Ou ...
- 【左偏树+贪心】BZOJ1367-[Baltic2004]sequence
[题目大意] 给定一个序列t1,t2,...,tn ,求一个递增序列z1<z2<...<zn , 使得R=|t1−z1|+|t2−z2|+...+|tn−zn| 的值最小.本题中,我 ...
随机推荐
- JDBC如何解决乱码
只要在连接URL字符里添加参数 ?useUnicode=true&characterEncoding=utf-8 完整的URL字符串如下: 1 String url = "jdbc: ...
- 有哪些不同类型的IOC(依赖注入)方式?
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖. Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参stati ...
- System.getenv和getProperty的区别
/** * System.getenv()是获取---环境变量(environment variables), * 系统层面的,好比我linux系统里的.bash_profile文件里面的变量 * 返 ...
- 分布式集群中为什么会有 Master?
在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机 器可以共享这个结果,这样可以大大减少重复计算,提高性能,于是就需要进行 leader 选举.
- 服务端处理 Watcher 实现 ?
1.服务端接收 Watcher 并存储 接收到客户端请求,处理请求判断是否需要注册 Watcher,需要的话将数据节点 的节点路径和 ServerCnxn(ServerCnxn 代表一个客户端和服务端 ...
- 什么是基于 Java 的 Spring 注解配置?
基于 Java 的配置,允许你在少量的 Java 注解的帮助下,进行你的大部分 Spring 配置而非通过 XML 文件. 以@Configuration 注解为例,它用来标记类可以当做一个 bean ...
- docker 容器简单使用
文章目录 docker简介 docker容器简单使用 1.HelloWorld 2.运行交互式的容器 3.启动容器(后台模式) 安装docker容器的博文有很多这里就不做过多赘述了,另外如果不想安装d ...
- 4.2 ROS节点运行管理launch文件
4.2 ROS节点运行管理launch文件 关于 launch 文件的使用我们已经不陌生了,在第一章内容中,就曾经介绍到: 一个程序中可能需要启动多个节点,比如:ROS 内置的小乌龟案例,如果要控制乌 ...
- pandas学习总结
什么是pandas pandas数据读取 03. Pandas数据结构 Pandas查询数据的几种方法
- matlab拟合函数的三种方法
方法一:多项式拟合polyfit 1 x=[1 2 3 4 5 6 7 8 9]; 2 3 y=[9 7 6 3 -1 2 5 7 20]; 4 P= polyfit(x, y, 3) %三阶多项式拟 ...