题目链接

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;
}

BZOJ1367 [Baltic2004]sequence 【左偏树】的更多相关文章

  1. bzoj1367 [Baltic2004]sequence 左偏树+贪心

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1367 题解 先考虑条件为要求不下降序列(不是递增)的情况. 那么考虑一段数值相同的子段,这一段 ...

  2. BZOJ1367: [Baltic2004]sequence(左偏树)

    Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 解题思路: 有趣的数学题. 首先确定序 ...

  3. 【BZOJ1367】[Baltic2004]sequence 左偏树

    [BZOJ1367][Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sampl ...

  4. BZOJ1367 BOI2004Sequence(左偏树)

    首先考虑把bi和ai同时减i,问题变为非严格递增.显然如果a是一个递减序列,b序列所有数都取其中位数最优.于是划分原序列使得每一部分递减,然后考虑合并相邻两段.如果前一段的中位数<=后一段的中位 ...

  5. bzoj 1367 [ Baltic 2004 ] sequence —— 左偏树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1367 好题啊!论文上的题: 论文上只给出了不下降序列的求法: 先考虑特殊情况,如果原序列上升 ...

  6. BZOJ1367 [Baltic2004]sequence 堆 左偏树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1367 题意概括 Description Input Output 一个整数R 题解 http:// ...

  7. 【BZOJ 1367】 1367: [Baltic2004]sequence (可并堆-左偏树)

    1367: [Baltic2004]sequence Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Ou ...

  8. 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]

    题目传送门 数字序列 题目描述 给定一个整数序列 a1​,a2​,⋅⋅⋅,an​ ,求出一个递增序列 b1​<b2​<⋅⋅⋅<bn​ ,使得序列 ai​ 和 bi​ 的各项之差的绝对 ...

  9. [BOI2004]Sequence 数字序列(左偏树)

    PS:参考了黄源河的论文<左偏树的特点及其应用> 题目描述:给定一个整数序列\(a_1, a_2, - , a_n\),求一个递增序列\(b_1 < b_2 < - < ...

随机推荐

  1. 逆向某停车app(原创)

    最近一直在做python开发的事情,信息安全方面做得很少,也是"蛋蛋"的忧伤呀.今天有朋友请我帮忙,将一个app里的文字和图标替换一下,花了一下午和一晚上的时间搞了一下,主要是图标 ...

  2. 我们一起学习WCF 第四篇单通讯和双向通讯

    前言:由于个人原因很久没有更新这个系列了,我会继续的更新这系列的文章.这一章是单向和双向通讯.所谓的单向就是只有发送却没有回复,双向是既有发送还有回复.就是有来无往代表单向,礼尚往来表示双向.下面我用 ...

  3. Introduction to Locking in SQL Server

    Locking is a major part of every RDBMS and is important to know about. It is a database functionalit ...

  4. 高可用Kubernetes集群-8. 部署kube-scheduler

    十.部署kube-scheduler kube-scheduler是Kube-Master相关的3个服务之一,是有状态的服务,会修改集群的状态信息. 如果多个master节点上的相关服务同时生效,则会 ...

  5. Focalprice李培亮:梦想让人在我店里排队

    [亿邦动力网讯]4月3日消息,外贸B2C平台Focalprice总裁李培亮日前亮相亿邦动力网联合河南省商务厅举办的“第九届中国中小企业电子商务大会暨2014中国(河南)跨境贸易电子商务峰会”,表达自己 ...

  6. DX孟虎点评新兴市场:巴西俄罗斯火爆背后

    [亿邦动力网讯]4月3日消息,在第九届中国中小企业电子商务大会暨2014中国(河南)跨境贸易电子商务峰会上,DX公司CEO孟虎对新兴市场做了详细的分析,指出在当今的跨境电商环境下,北美.西欧作为电商成 ...

  7. app开发相关

    app播放UIWebview 没有声音解决: 设置 allowsInlineMediaPlayback  = YES; mediaPlaybackRequiresUserAction = NO

  8. 团队项目成员与题目(本地地铁查询app)

    团队名称:Daydreaming团队成员及其特点:张运涛:能快速与团队成员中的每一位进行合作,能全面考虑遇到的问题,善于总结积累.能较好的理解老师与其他人员的想法要求.刘瑞欣:做事果断,善于领导,有想 ...

  9. 字典树---2001 POJ Shortest Prefixes(找最短前缀)

    做的第一道字典树的题,算比较水的: -->>>:传送门 代码: #include <stdio.h> #include<stdlib.h> #define M ...

  10. IT小小鸟阅读笔记

    人生就像是一艘漂泊的船,你努力滑行了就会找到成功的彼岸,否则就漂泊一生.在这个物欲横流的时代有太多的诱惑使我们静不下心来,但是我们应该时时刻刻警醒自己要做一些对自己成长有意义的事,程序员虽然幸苦但是作 ...