[Baltic2004]数字序列
原题请见《左偏树的特点及其应用》BY 广东省中山市第一中学 黄源河
luogu
题意
给出序列\(a[1...n]\),要求构造一个不下降序列\(b[1...n]\)使得\(\sum_{i=1}^{n}|a_i-b_i|\)最小。
sol
首先很自然地能够想到,构造出来的序列\(b[1...n]\)一定可以划分成\(m\)段\((1\le{m}\le{n})\),每段内数字全部相同。
我们把每一段的数字提取出来分别为\(c[1...m]\)。
如果对每一段的\(c[i]\)都取最优的话,那么一定是去这一段中\(a[i]\)的中位数。
但是取中位数可能会导致序列\(c\)不满足非降,这个时候就需要把相邻的两个不合法的段合并成一段。
所以就需要维护中位数。
左偏树。对于一个长度为\(x\)的段,左偏树中保存这一段中前\(\lfloor\frac{x+1}{2}\rfloor\)小的数字,易知这些数里面最大的那个就是中位数,合并的时候直接合并两棵左偏树。
因为\(\lfloor\frac{x+1}{2}\rfloor+\lfloor\frac{y+1}{2}\rfloor=\lfloor\frac{x+y+1}{2}\rfloor-1\)当且仅当\(x,y\)均为奇数,所以这种情况要弹掉堆顶元素。
复杂度\(O(n\log{n})\)
注:洛谷的题目是要求构造一个递增序列,可以采用减下标的方法,即输入时把每个数都减去对应下表,输出时再加上,这样就可以完成不下降序列和递增序列的转换。
code
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
inline int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e6+5;
int n,key[N],ls[N],rs[N],dis[N],S[N],ed[N],top;
ll ans;
int merge(int A,int B)
{
if (!A||!B) return A|B;
if (key[A]<key[B]) swap(A,B);
rs[A]=merge(rs[A],B);
if (dis[ls[A]]<dis[rs[A]]) swap(ls[A],rs[A]);
dis[A]=dis[rs[A]]+1;
return A;
}
int main()
{
n=gi();
for (int i=1;i<=n;++i) key[i]=gi();
for (int i=1;i<=n;++i)
{
++top;S[top]=i;ed[top]=i;
while (top>1&&key[S[top]]<key[S[top-1]])
{
--top;
S[top]=merge(S[top],S[top+1]);
if (((ed[top+1]-ed[top])&1)&&((ed[top]-ed[top-1])&1))
S[top]=merge(ls[S[top]],rs[S[top]]);
ed[top]=ed[top+1];
}
}
for (int i=1;i<=top;++i)
for (int j=ed[i-1]+1;j<=ed[i];++j)
ans+=abs(key[j]-key[S[i]]);
printf("%lld\n",ans);
return 0;
}
强行再贴一个洛谷上那道题的代码
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
inline int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e6+5;
int n,key[N],ls[N],rs[N],dis[N],S[N],ed[N],top;
ll ans;
int merge(int A,int B)
{
if (!A||!B) return A|B;
if (key[A]<key[B]) swap(A,B);
rs[A]=merge(rs[A],B);
if (dis[ls[A]]<dis[rs[A]]) swap(ls[A],rs[A]);
dis[A]=dis[rs[A]]+1;
return A;
}
int main()
{
n=gi();
for (int i=1;i<=n;++i) key[i]=gi()-i;
for (int i=1;i<=n;++i)
{
++top;S[top]=i;ed[top]=i;
while (top>1&&key[S[top]]<key[S[top-1]])
{
--top;
S[top]=merge(S[top],S[top+1]);
if (((ed[top+1]-ed[top])&1)&&((ed[top]-ed[top-1])&1))
S[top]=merge(ls[S[top]],rs[S[top]]);
ed[top]=ed[top+1];
}
}
for (int i=1;i<=top;++i)
for (int j=ed[i-1]+1;j<=ed[i];++j)
ans+=abs(key[j]-key[S[i]]);
printf("%lld\n",ans);
for (int i=1;i<=top;++i)
for (int j=ed[i-1]+1;j<=ed[i];++j)
printf("%d ",key[S[i]]+j);
puts("");return 0;
}
[Baltic2004]数字序列的更多相关文章
- [Luogu4331][Baltic2004]数字序列
原题请见<左偏树的特点及其应用>BY 广东省中山市第一中学 黄源河 luogu 题意 给出序列\(a[1...n]\),要求构造一个不下降序列\(b[1...n]\)使得\(\sum_{i ...
- 找出数组中最长的连续数字序列(JavaScript实现)
原始题目: 给定一个无序的整数序列, 找最长的连续数字序列. 例如: 给定[100, 4, 200, 1, 3, 2], 最长的连续数字序列是[1, 2, 3, 4]. 小菜给出的解法: functi ...
- 九度OJ 1544 数字序列区间最小值
题目地址:http://ac.jobdu.com/problem.php?pid=1544 题目描述: 给定一个数字序列,查询任意给定区间内数字的最小值. 输入: 输入包含多组测试用例,每组测试用例的 ...
- 【BZOJ】【1049】【HAOI2006】数字序列
DP 第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT 题解:http://pan.baidu.com/share/ ...
- kaggle之数字序列预测
数字序列预测 Github地址 Kaggle地址 # -*- coding: UTF-8 -*- %matplotlib inline import pandas as pd import strin ...
- string 数字序列大小比较
string 数字序列大小比较 string.compare string a = "022"; string b="1"; 比较结果 '022' < ' ...
- codevs 2622 数字序列
2622 数字序列 提交地址:http://codevs.cn/problem/2622/ 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 De ...
- Shell生成数字序列
转自http://kodango.com/generate-number-sequence-in-shell Shell里怎么输出指定的数字序列: for i in {1..5}; do echo $ ...
- 《剑指offer》第四十四题(数字序列中某一位的数字)
// 面试题44:数字序列中某一位的数字 // 题目:数字以0123456789101112131415…的格式序列化到一个字符序列中.在这 // 个序列中,第5位(从0开始计数)是5,第13位是1, ...
随机推荐
- React项目模板-从项目搭建到部署
前一段时间做了一个小项目,时间比较紧,就一个人月.最终希望能够通过微信公众号链接启动应用. 项目的业务细节就不多说了,主要是想分享一下做这个项目技术方面的一些经验. 技术选型 参考范围大致三种:Ang ...
- Hive metastore表结构设计分析
今天总结下,Hive metastore的结构设计.什么是metadata呢,对于它的描述,可以理解为数据的数据,主要是描述数据的属性的信息.它是用来支持如存储位置.历史数据.资源查找.文件记录等功能 ...
- gitlab项目迁移
ALL Git* => Gitlab Nothing, Just copy the git URL to gitlab(类似于 fork) 使用 Git Mirror 無痛轉移 Git Serv ...
- Mysql(三)-2:数据类型
一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob.com/mysql/mysql-data ...
- PV IP UV
PV(访问量) Page View,页面浏览量. 具体的说,就是在一天内,该网站的页面总共访问了多少次 IP(独立IP) 一天内访问网站的IP数量 UV(独立访客) Unique Visitor 一般 ...
- 关于HTTP,你知道哪些?
HTTP简介 HTTP 的全称是 Hypertext Transfer Protocol,超文本传输协议 规定客户端和服务器之间的数据传输格式 让客户端和服务器能有效地进行数据沟通 HTTP 协议是网 ...
- 来了解并防范一下CSRF攻击提高网站安全
看一下我从网上找的原理图,结合举例描述,多看一遍你就知道怎么回事了. CSRF是什么呢?CSRF全名是Cross-site request forgery,是一种对网站的恶意利用,CSRF比XSS更具 ...
- Python 实现单例模式的一些思考
一.问题:Python中如何实现单例模式 单例模式指一个类只能实例化一个对象. 二.解决方案: 所有资料参考于: http://python.jobbole.com/87294/ https://ww ...
- c# 委托(Func、Action)
以前自己写委托都用 delegate, 最近看组里的大佬们都用 Func , 以及 Action 来实现, 代码简洁了不少, 但是看得我晕晕乎乎. 花点时间研究一下,记录一下,以便后期的查阅. 1.F ...
- ubuntu14.04 安装Jenkins
wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add - sudo sh -c 'ec ...