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| 的值最小.本题中,我 ...
随机推荐
- python单ip端口扫描器
from socket import * import threading #导入线程相关模块 # qianxiao996精心制作 #博客地址:https://blog.csdn.net/qq_363 ...
- 学习SpringMVC必知必会(2)~走近Spring MVC
一.Spring 基本介绍 1.什么是 Spring MVC? SpringMVC 是 Spring-Frame 框架的子集(Spring-Frame包含了Spring MVC), MVC 框架,(类 ...
- S120通讯报文应用类型及区别,PZD格式及意义 | 标准报文1/2/3/4/5/6/7/9/20/81/82/83,西门子报文
一.报文功能图 1.1标准报文 适用于驱动器 SINAMICS S120 S150 参数手册 章节3.9 PROFIdrive 图3-36 功能图2415标准报文和过程数据1 SINAMICS S12 ...
- IOC的优点是什么?
IOC 或 依赖注入把应用的代码量降到最低.它使应用容易测试,单元测试不再需要单例和JNDI查找机制.最小的代价和最小的侵入性使松散耦合得以实现.IOC容器支持加载服务时的饿汉式初始化和懒加载.
- Dubbo 服务降级,失败重试怎么做?
可以通过 dubbo:reference 中设置 mock="return null".mock 的值也可以修 改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名 ...
- Kafka 分区数可以增加或减少吗?为什么?
我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka 不支持减少分区数. Kafka 分区数据不支持减少是由很多原因的,比如减少的分 ...
- uWSGI+django+nginx的工作原理流程与部署
二.必要的前提 2.1 准备知识 django 一个基于python的开源web框架,请确保自己熟悉它的框架目录结构. uWSGI 一个基于自有的uwsgi协议.wsgi协议和http服务协议的web ...
- spring DAO 有什么用?
Spring DAO 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一 种统一的方式工作.这使得用户容易在持久性技术之间切换.它还允许您在编写 代码时,无需考虑捕获每种技术 ...
- Math.round(11.5) 等于多少?Math.round(-11.5)等于 多少?
Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11.四舍五 入的原理是在参数上加 0.5 然后进行下取整.
- 机器学习优化算法之EM算法
EM算法简介 EM算法其实是一类算法的总称.EM算法分为E-Step和M-Step两步.EM算法的应用范围很广,基本机器学习需要迭代优化参数的模型在优化时都可以使用EM算法. EM算法的思想和过程 E ...