题目链接

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. [转载]A cycle was detected in the build path of project

    解决Eclipse中Java工程间循环引用而报错的问题 如果我们的项目包含多个工程(project),而它们之间又是循环引用的关系,那么Eclipse在编译时会抛出如下一个错误信息: “A cycle ...

  2. [转]50 Tips for Working with Unity (Best Practices)

    About these tips These tips are not all applicable to every project. They are based on my experience ...

  3. while read读取文本内容

    读取文件给 while 循环 方式一: exec <FILE while read line do cmd done 方式二: cat FILE_PATH |while read line do ...

  4. LeetCode--147.对链表进行插入排序

    题目描述: 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插入排序算法 ...

  5. SQL行列轉換方法(詳細例子)

    普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法. 问题:假设有张学生成绩表(tb)如下 ...

  6. “Hello World!”团队第十四次会议

    今天是我们团队“Hello World!”团队召开的第十四次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.Todo List 六.会议照片 七.燃尽图 一.会议时间 2 ...

  7. multipart/form-data post 方法提交表单,后台获取不到数据

    这个和servlet容器有关系,比如tomcat等. 1.get方式 get方式提交的话,表单项都保存在http header中,格式是 http://localhost:8080/hello.do? ...

  8. 软工实践-Alpha 冲刺 (8/10)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成非功能的主界面制作 ...

  9. mysql hql异常

    org.springframework.dao.InvalidDataAccessResourceUsageException:  could not execute query; nested ex ...

  10. HDU 1277 Nested Dolls

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1677 题意: 玩俄罗斯套娃,问最后至少还剩几个. 题解: 这题可以和拦截导弹做对比,因为这里是二维的 ...