题面描述

给定整数数组$a_1,a_2,a_3...a_n$,求递增数组$b_1,b_2,b_3...b_n$

使得$|a_1 - b_1| + |a_2 - b_2| + ... + |a_n - b_n|$最大

吐槽:

这道题不是人能想出来的,太神了

很有收获?$or\; not\;?$

题解:

考虑$b$数组严格递增这个条件过于苛刻,期望$b$数组不严格递增

那么,由于$b_1 < b_2 < ... < b_n$,有$b_1 - 1 \leq b_2 - 2 ... \leq b_n - n$

我们不妨考虑新的$b'_i = b_i - i$

在$b'_i$对$a'_i = a_i - i$取到最优时,$b_i$同时对$a_i$取到最优

这时,$b‘_i$就可以相等了

两个性质

1. 对于$a'_1 \leq a'_2 \leq ... \leq a'_n$,我们取$b'i = a'i$最优

2. 对于$a'_1 \geq a'_2 \geq ... \geq a'_n$,我们取$b'i$为中位数最优

并且由于$b'_i$相等,$a'_1, a'_2...a'_n$可以任意的排列

因此,我们不妨假设已经处理好了前$i - 1$个数,正要加入第$i$个数

我们假设维护出来的$b'_i$相同的并成一个区间,$b'_i$取这个区间的中位数

对于$a'_i > b'_{i - 1}$,取$b'_i = a'_i$时,相等于递增序列

否则$a'_i < b'_{i - 1}$,我们把$i$并入$b'_{i - 1}$,得到新的中位数(因为顺序任意,所以怎么合都没问题),并继续检查

那么,我们要做的事其实就是

1. 快速合并两个区间中的数

2. 确定出区间中的中位数

左偏树就是不错的选择

复杂度$O(n\log n)$

#include <cstdio>
#include <cmath>
#include <iostream>
#define sid 1000500
#define ll long long
#define ri register int
#define ls(o) t[o].ls
#define rs(o) t[o].rs
using namespace std; char RR[];
#define isdigit(u) (u >= '0' && u <= '9')
extern inline char gc() {
static char *S = RR + , *T = RR + ;
if(S == T) S = RR, fread(RR, , , stdin);
return *S ++;
}
inline int read() {
int o = , w = ; char c = gc();
while(!isdigit(c)) {if(c == '-') w = -; c = gc();}
while(isdigit(c)) o = o * + c - '', c = gc();
return o * w;
} int n, cnt;
int rt[sid], ld[sid], rd[sid], a[sid];
struct reHeap {
int ls, rs, sz, npl, key;
} t[sid]; inline void update(int o) {
t[o].sz = t[ls(o)].sz + t[rs(o)].sz + ;
t[o].npl = t[rs(o)].npl + ;
} int merge(int x, int y) {
if(!x || !y) return x + y;
if(t[x].key < t[y].key) swap(x, y);
rs(x) = merge(rs(x), y);
if(t[rs(x)].npl > t[ls(x)].npl) swap(ls(x), rs(x));
update(x); return x;
} int main() {
n = read();
for(ri i = ; i <= n; i ++) {
ld[++ cnt] = rd[cnt] = rt[cnt] = i;
a[i] = t[i].key = read() - i; t[i].sz = ;
while(cnt > && t[rt[cnt]].key < t[rt[cnt - ]].key) {
cnt --; rd[cnt] = rd[cnt + ];
rt[cnt] = merge(rt[cnt], rt[cnt + ]);
while(t[rt[cnt]].sz * > rd[cnt] - ld[cnt] + )
rt[cnt] = merge(ls(rt[cnt]), rs(rt[cnt]));
}
}
ll ans = ;
for(ri i = ; i <= cnt; i ++)
for(ri j = ld[i]; j <= rd[i]; j ++)
ans += abs(t[rt[i]].key - a[j]);
printf("%lld\n", ans);
for(ri i = ; i <= cnt; i ++)
for(ri j = ld[i]; j <= rd[i]; j ++)
printf("%d ", t[rt[i]].key + j);
return ;
}

[BOI2004]Sequence的更多相关文章

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

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

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

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

  3. [BOI2004]Sequence 数字序列

    Description: Hint: \(n<=10^5\) Solution: 首先考虑b不严格递增时的做法 发现当\(a[i]\)递增时\(b[i]\)直接取\(a[i]\)即可,否则此时需 ...

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

    [题目链接] https://www.luogu.org/problemnew/show/P4331 题目描述 给定一个整数序列\(a_1, a_2, ··· , a_n,\)求出一个递增序列\(b_ ...

  5. 洛谷P4331 [BOI2004]Sequence 数字序列(左偏树)

    传送门 感觉……不是很看得懂题解在说什么? 我们先把原数列$a_i-=i$,那么本来要求递增序列,现在只需要求一个非严格递增的就行了(可以看做最后每个$b_i+=i$,那么非严格递增会变为递增) 如果 ...

  6. luoguP4331 [BOI2004]Sequence 数字序列

    题意 大力猜结论. 首先将所有\(a_i\)变为\(a_i-i\),之后求不严格递增的\(b_i\),显然答案不变,最后\(b_i\)加上\(i\)即可. 考虑两种特殊情况: 1.\(a[]\)是递增 ...

  7. Luogu P4331 [BOI2004]Sequence 数字序列 (左偏树论文题)

    清晰明了%%% Fairycastle的博客 个人习惯把size什么的存在左偏树结点内,这样在外面好写,在里面就是模板(只用修改update). 可以对比一下代码(好像也差不多-) MY CODE # ...

  8. 洛谷P4331[BOI2004] sequence

    博客复活? 这个题很模板啊.随便上个左偏树.之前第一遍写对了.然后今天翻出来又写了一遍发现了一个奇奇怪怪的问题. 对比如下 上面的是AC 下面的WA 真的是一个很蠢的问题...你TM堆顶都弹出来了,堆 ...

  9. 洛谷$P4331\ [BOI2004]\ Sequence$ 数字序列 左偏树

    正解:左偏树 解题报告: 传送门$QwQ$ 开始看到的时候$jio$得长得很像之前做的一个$dp$,,, 但是$dp$那题是说不严格这里是严格? 不难想到我们可以让$a_{i},b_{i}$同时减去$ ...

随机推荐

  1. 在Unity中实现屏幕空间阴影(1)

    接着上篇文章,我们实现了SSR效果. 其中的在屏幕空间进行光线追踪的方法是通用的.借此我们再实现一种屏幕空间的效果,即屏幕空间阴影. 文中的图片来自Catlike coding http://catl ...

  2. 【leetcode 简单】第四题 罗马数字转整数

    罗马数字包含以下七种字符:I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并列 ...

  3. NYOJ 117 求逆序数 (树状数组)

    题目链接 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出 ...

  4. 天梯赛 L2-006 树的遍历 (二叉树)

    给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(<=30),是二叉树中结点的个数.第二行给出其后序遍历序 ...

  5. 25、Python垃圾回收机制?

    Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾.在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的 ...

  6. Caffe提取任意层特征并进行可视化

    现在Caffe的Matlab接口 (matcaffe3) 和python接口都非常强大, 可以直接提取任意层的feature map以及parameters, 所以本文仅仅作为参考, 更多最新的信息请 ...

  7. mysql数据库单表增删改查命令

    数据库DB-database-mysql 课程安排 第一天: 1.数据库定义以及设计 2.mysql服务端的安装 3.mysql-dos操作 库的操作 表的操作 4.mysql客户端navicate工 ...

  8. 【swupdate文档 四】SWUpdate:使用默认解析器的语法和标记

    SWUpdate:使用默认解析器的语法和标记 介绍 SWUpdate使用库"libconfig"作为镜像描述的默认解析器. 但是,可以扩展SWUpdate并添加一个自己的解析器, ...

  9. BZOJ 2049: [Sdoi2008]Cave 洞穴勘测——LCT

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2049 省选之前来切一道数据结构模板题. 题意 这是一道模板题. N个点,M次操作,每次加边/ ...

  10. selenium grid应用1-多浏览器执行用例

    driver =webdriver.Remote(command_executor=’http://127.0.0.1:4444/wd/hub’, desired_capabilities=Desir ...