题目链接

BZOJ1367

题解

又是一道神题,,

我们考虑一些简单的情况:
我们先假设\(b_i\)单调不降,而不是递增
对于递增序列\(\{a_i\}\),显然答案\(\{b_i\}\)满足\(b_i = a_i\)
对于递减序列\(\{a_i\}\),显然答案\(\{b_i\}\)满足\(b_i\)为\(a_i\)的中位数

于是我们有了初步的想法:
将\(a_i\)分成若干个单调递减的段,每段的答案为其中位数
然后顺次访问段
如果两段的答案是递增的,显然这两段就没有影响,相互独立了,就保留答案
如果相邻两段的答案是递减的,就合并这两段,重新寻找它们的中位数
可以证明是对的

对于单调递增的处理,我们只需令\(A[i] = A[i] - i\),即可转变为单调不下降
维护中位数可以用对顶堆实现,由于涉及堆的合并,那就使用左偏树

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 1000005,maxm = 100005,INF = 1000000000;
inline int read(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag;
}
int val[maxn],ls[maxn],rs[maxn],d[maxn],siz[maxn],rt[maxn],Rt[maxn];
int merge(int a,int b){if (!b) return a;if (!a) return b;if (val[b] < val[a]) swap(a,b);rs[a] = merge(rs[a],b);siz[a] = siz[ls[a]] + 1 + siz[rs[a]];if (d[ls[a]] < d[rs[a]]) swap(ls[a],rs[a]);d[a] = rs[a] ? d[rs[a]] + 1 : 0;return a;
}
int Merge(int a,int b){if (!b) return a;if (!a) return b;if (val[b] > val[a]) swap(a,b);rs[a] = Merge(rs[a],b);siz[a] = siz[ls[a]] + 1 + siz[rs[a]];if (d[ls[a]] < d[rs[a]]) swap(ls[a],rs[a]);d[a] = d[rs[a]] + 1;return a;
}
int n,pos[maxn],len[maxn],K;
LL A[maxn];
void work(){int tmp; d[0] = -1;for (int i = 1; i <= n; i++){pos[++K] = i; len[K] = 1; rt[i] = i; siz[rt[i]] = 1; val[i] = A[i];while (K > 1 && val[rt[pos[K]]] < val[rt[pos[K - 1]]]){K--;rt[pos[K]] = merge(rt[pos[K]],rt[pos[K + 1]]);Rt[pos[K]] = Merge(Rt[pos[K]],Rt[pos[K + 1]]);len[K] += len[K + 1];while (siz[rt[pos[K]]] > siz[Rt[pos[K]]]){tmp = rt[pos[K]];rt[pos[K]] = merge(ls[rt[pos[K]]],rs[rt[pos[K]]]);ls[tmp] = rs[tmp] = 0; siz[tmp] = 1;Rt[pos[K]] = Merge(Rt[pos[K]],tmp);}while (siz[rt[pos[K]]] < siz[Rt[pos[K]]]){tmp = Rt[pos[K]];Rt[pos[K]] = Merge(ls[Rt[pos[K]]],rs[Rt[pos[K]]]);ls[tmp] = rs[tmp] = 0; siz[tmp] = 1;rt[pos[K]] = merge(rt[pos[K]],tmp);}}//printf("[%d,%d]  mid = %d\n",i - len[K] + 1,i,val[rt[pos[K]]]);}LL ans = 0,v;for (int i = 1,l = 1; i <= K; i++){v = siz[rt[pos[i]]] > siz[Rt[pos[i]]] ? val[rt[pos[i]]] : val[Rt[pos[i]]];//printf("[%d,%d]  v = %lld\n",l,l + len[i] - 1,v);for (int j = 0; j < len[i]; j++)ans += abs(v - A[l + j]);l += len[i];}printf("%lld\n",ans);
}
int main(){n = read();REP(i,n) A[i] = read() - i;//REP(i,n) printf("%lld ",A[i]); puts("");work();return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/9202443.html

BZOJ1367 [Baltic2004]sequence 【左偏树】相关推荐

  1. 【学习笔记】浅谈短小可爱的左偏树(可并堆)

    文章目录 左偏树 左偏树的合并(merge)操作 例题 罗马游戏 [Apio2012]dispatching [JLOI2015]城池攻占 [Baltic2004]sequence 左偏树 左偏树是一 ...

  2. P4331-[BalticOI2004]Sequence数字序列【左偏树】

    正题 题目链接:https://www.luogu.com.cn/problem/P4331 题目大意 给出一个序列aaa,求一个单调上升的序列bbb使得∑i=1n∣ai−bi∣\sum_{i=1}^ ...

  3. 左偏树(可并堆)初步及其应用

    作者:hsez_yyh 链接:左偏树(可并堆)初步及其应用_hsez_yyh的博客-CSDN博客 来源:湖北省黄石二中信息竞赛组        著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  4. 《程序设计解题策略》——1.6 利用左偏树实现优先队列的合并

    本节书摘来自华章计算机<程序设计解题策略>一书中的第1章,第1.6节,作者:吴永辉 王建德 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1.6 利用左偏树实 ...

  5. 【洛谷3377】 左偏树(可并堆)

    前言 其实我是不小心翻线性基的时候看见的. Solution 左偏树只会模板,挖坑待补 代码实现 #include<stdio.h> #include<stdlib.h> #i ...

  6. P3642 [APIO2016]烟火表演(左偏树、函数)

    解析 感觉是左偏树的神题了. 首先有一个比较显然的结论,一个合法的方案中,两个叶子到它们 lca\text{lca}lca 的距离必须相等. 考虑设计 dp\text{dp}dp : fi,xf_{i ...

  7. YbtOJ#631-次短路径【左偏树,最短路】

    正题 题目链接:https://www.ybtoj.com.cn/contest/114/problem/1 题目大意 给出nnn个点mmm条边的一张无向图,对于每个点iii求不经过i∼1i\sim ...

  8. P1552-[APIO2012]派遣【左偏树】

    正题 题目链接:https://www.luogu.com.cn/problem/P1552 题目大意 一个nnn个点森林,每个点有价值和代价,选择一个点并在这个点的子树中选择一些点使得. 选择的点数 ...

  9. P3377-[模板]左偏树(可并堆)

    正题 题目链接:https://www.luogu.com.cn/problem/P3377 题目大意 开始时nnn个只有一个数的集合,要求支持 合并两个集合 查询一个集合中的最小值并删除 解题思路 ...

  10. HDU1512 (左偏树)

    2.1.2 可并堆的定义 可并堆(Mergeable Heap)也是一种抽象数据类型,它除了支持优先队列的三个基本操作(Insert, Minimum, Delete-Min),还支持一个额外的操作- ...

最新文章

  1. 2022-2028年中国干电池制造行业产销需求与投资预测分析报告
  2. Keras输出网络结构图
  3. 编写高性能的 JavaScript 程序的几个提示
  4. 【数据结构】双链表的应用
  5. PowerDesigner导入MySQL数据库表
  6. python写excel文件出错_【求教】xlutils修改中文Excel文件出错
  7. PageRank算法简介及Map-Reduce实现
  8. ASP.NETCore小技巧:使用测试用户中间件
  9. 玩转运维编排服务的权限:Assume Role+Pass Role
  10. (53)Verilog HDL上升沿采样
  11. 从Nand Flash启动U-BOOT的基本原理
  12. python3l下载_lunix 安装python3
  13. 1900页Python系列PPT分享二:Python序列(列表、元组、字典、集合)(154页)
  14. 洛谷P1079 Vigenère 密码
  15. 你必须知道的.NET
  16. Beta阶段第四次Scrum Meeting
  17. 每日算法之三十五:Wildcard Matching
  18. 模糊控制在matlab的实现,模糊控制系统的MATLAB实现
  19. 编译原理的有限自动机
  20. 人脸检测——基于face_recognition库

热门文章

  1. iOS多线程之5.GCD的基本使用
  2. 汇编---3---物理地址
  3. 粒子群算法(1)----粒子群算法简单介绍
  4. avrdude: stk500_getsync(): not in sync: resp=0x00
  5. H2介绍 – Java嵌入式数据库
  6. 简约的网络字节序处理
  7. 根据数据库中的数据构造treeview
  8. xmlhttp上传文件(转贴)
  9. 解决Eclipse 64位启动时,报jvm.dll错
  10. 周末内部常用的15款开发者工具