P4331-[BalticOI2004]Sequence数字序列【左偏树】
正题
题目链接:https://www.luogu.com.cn/problem/P4331
题目大意
给出一个序列aaa,求一个单调上升的序列bbb使得∑i=1n∣ai−bi∣\sum_{i=1}^n|a_i-b_i|∑i=1n∣ai−bi∣最小。
解题思路
巧妙的解法
首先我们让所有的ai−ia_i-iai−i这样我们求的bbb序列就只需要满足单调不降。
然后考虑特殊情况
- 对于一串连续的满足ax≤ax+1a_x\leq a_{x+1}ax≤ax+1那么这一段的bx=axb_x=a_xbx=ax
- 对于一串连续的满足ax≥ax+1a_x\geq a_{x+1}ax≥ax+1那么这一段的bxb_xbx为这一段数的中位数
而且对于连续的两个区间(L,mid)(L,mid)(L,mid)和(mid+1,R)(mid+1,R)(mid+1,R)的局部最优解也满足一下性质,所以就有做法:
我们维护若干段局部最优解www,每次加入一个数aia_iai如果满足ai≥wcnta_i\geq w_{cnt}ai≥wcnt那么有bi=aib_i=a_ibi=ai。如果ai≤wcnta_i\leq w_{cnt}ai≤wcnt那么我们就将aia_iai合并入前面的局部最优解,并重新计算这一段的中位数后继续看是否需要与前面合并(即判断是否wcnt≥wcnt−1w_{cnt}\geq w_{cnt-1}wcnt≥wcnt−1)。
我们可以左偏树做到动态合并和维护中位数(保持堆中个数为一半即可)。时间复杂度O(nlogn)O(n\log n)O(nlogn)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int n,cnt,a[N],rt[N],L[N],R[N];
int t[N][2],dis[N],val[N],siz[N];
long long ans;
int Merge(int x,int y){if(!x||!y)return x+y;if(val[x]<val[y])swap(x,y);int &ls=t[x][0],&rs=t[x][1];rs=Merge(rs,y);if(dis[ls]<dis[rs])swap(ls,rs);dis[x]=dis[ls]+1;return x;
}
void Pop(int x)
{siz[x]--;rt[x]=Merge(t[rt[x]][0],t[rt[x]][1]);}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]-=i;for(int i=1;i<=n;i++){siz[++cnt]=1;val[i]=a[i];rt[cnt]=i;L[cnt]=R[cnt]=i;while(cnt>1&&val[rt[cnt-1]]>val[rt[cnt]]){cnt--;siz[cnt]+=siz[cnt+1];R[cnt]=R[cnt+1];rt[cnt]=Merge(rt[cnt],rt[cnt+1]);while(siz[cnt]>(R[cnt]-L[cnt])/2+1)Pop(cnt);}}for(int i=1;i<=cnt;i++)for(int j=L[i];j<=R[i];j++)ans+=abs(a[j]-val[rt[i]]);printf("%lld\n",ans);for(int i=1;i<=cnt;i++)for(int j=L[i];j<=R[i];j++)printf("%d ",val[rt[i]]+j);
}
P4331-[BalticOI2004]Sequence数字序列【左偏树】相关推荐
- P4331 [BalticOI 2004]Sequence 数字序列(左偏树)
P4331 [BalticOI 2004]Sequence 数字序列 给定一个序列整数a1,a2,a3,-,an−1,ana_1, a_2, a_3, \dots, a_{n - 1}, a_na1 ...
- 左偏树(可并堆)初步及其应用
作者:hsez_yyh 链接:左偏树(可并堆)初步及其应用_hsez_yyh的博客-CSDN博客 来源:湖北省黄石二中信息竞赛组 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
- 《程序设计解题策略》——1.6 利用左偏树实现优先队列的合并
本节书摘来自华章计算机<程序设计解题策略>一书中的第1章,第1.6节,作者:吴永辉 王建德 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1.6 利用左偏树实 ...
- 【学习笔记】浅谈短小可爱的左偏树(可并堆)
文章目录 左偏树 左偏树的合并(merge)操作 例题 罗马游戏 [Apio2012]dispatching [JLOI2015]城池攻占 [Baltic2004]sequence 左偏树 左偏树是一 ...
- 一篇讲左偏树的好文章~
传送门:http://blog.csdn.net/iaccepted/article/details/6748038 二.左偏树的定义和性质.............................. ...
- [2018.12.6]左偏树
其实NOIp之前就学会了...结果咕到了现在... 我们都知道堆.但是很少有人会手写堆.因为我们有STL,而且手写堆码量不小(据说是吧?没写过). 而且堆的\(Merge\)操作又慢又麻烦. 于是就有 ...
- 左偏树初步学习 洛谷P3377
玩的有点多......睡的有点少... 左偏树是一种支持O(logn)的时间复杂度内进行合并的堆式数据结构. 定义: 外结点:左儿子或者右儿子是空结点的结点 距离:一个结点x的距离disx定义为其子树 ...
- 可并堆——左偏树 Leftist Heap
今天学习了左偏树,这是一个好理解而且好写的数据结构,和二叉堆一样可以在O(1)时间内取出优先级最高的值,O(logn)时间内删除优先级最高的值,不同的是如果要合并两个堆那么二叉堆就只能跪了.而左偏树能 ...
- Monkey King(左偏树 可并堆)
我们知道如果要我们给一个序列排序,按照某种大小顺序关系,我们很容易想到优先队列,的确很方便,但是优先队列也有解决不了的问题,当题目要求你把两个优先队列合并的时候,这就实现不了了 优先队列只有插入 删除 ...
最新文章
- vs编译报错C1020: 意外的 #endif
- 《UML大战需求分析》阅读笔记1
- JVM - 再聊GC垃圾收集算法及垃圾收集器
- 数据分析项目某电商app行为数据分析(1)
- Maven组件通过命令上传本地和私有仓库
- 如何让代码更易于维护_易于使用的单位和集成代码
- 灰度拉伸python_灰度变换之灰度线性拉伸(算法1)
- PHP7语法知识(三):时间与日期、表单、类与对象、正则表达式、错误异常处理、图像处理...
- python循环引用例子_魔幻离现实仅一步之遥:细说Python的循环调用、循环引用和循环导入...
- Latex 安装与配置
- 2022-2027年中国北斗卫星导航系统行业市场调研及未来发展趋势预测报告
- Google Earth Pro v7.3.6.9285 谷歌地球卫星图像专业版
- github加速方法
- Promethues原理详解
- unity 2022大三期末大作业 3D立体魔方游戏(附下载链接)
- opencv 图像拼接和图像融合技术
- 计算机二级java邓伦单_全国计算机等级考试计算机基础及Photoshop应用试题答案(2)...
- elasticsearch - 节点、集群分片及副本、CRUD
- python将一个字符串反转并输出_逆转字符串—输入一个字符串,将其逆转并输出。...
- C语言开发情人节玫瑰
热门文章
- 有没有测试人心里的软件,心理测评,认识自己的有效工具:(二)你做的可能是假的心理测试...
- 面试官问:你做过什么Java线程池实践,我写了一篇博客给他看~
- 独占设备的分配与回收_灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?...
- .net html5页面缓存,详解HTML5中的manifest缓存使用
- python分布式爬虫及数据存储_二十一 Python分布式爬虫打造搜索引擎Scrapy精讲—爬虫数据保存...
- 四川中级职称计算机考试考b级,四川省职称计算机B级考试1卷
- java的编译器怎么出来_怎样掌握ava编译器的使用,教程在这里,如何进行Java初级学习...
- AcWing 1047. 糖果
- linux查找应用主机,Linux 主机和服务器基本性能检查命令和工具
- 临界区、互斥量、信号量、事件的区别