[BOI2004]Sequence
题面描述
给定整数数组$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的更多相关文章
- 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]
题目传送门 数字序列 题目描述 给定一个整数序列 a1,a2,⋅⋅⋅,an ,求出一个递增序列 b1<b2<⋅⋅⋅<bn ,使得序列 ai 和 bi 的各项之差的绝对 ...
- [BOI2004]Sequence 数字序列(左偏树)
PS:参考了黄源河的论文<左偏树的特点及其应用> 题目描述:给定一个整数序列\(a_1, a_2, - , a_n\),求一个递增序列\(b_1 < b_2 < - < ...
- [BOI2004]Sequence 数字序列
Description: Hint: \(n<=10^5\) Solution: 首先考虑b不严格递增时的做法 发现当\(a[i]\)递增时\(b[i]\)直接取\(a[i]\)即可,否则此时需 ...
- P4331 [BOI2004]Sequence 数字序列 (左偏树)
[题目链接] https://www.luogu.org/problemnew/show/P4331 题目描述 给定一个整数序列\(a_1, a_2, ··· , a_n,\)求出一个递增序列\(b_ ...
- 洛谷P4331 [BOI2004]Sequence 数字序列(左偏树)
传送门 感觉……不是很看得懂题解在说什么? 我们先把原数列$a_i-=i$,那么本来要求递增序列,现在只需要求一个非严格递增的就行了(可以看做最后每个$b_i+=i$,那么非严格递增会变为递增) 如果 ...
- luoguP4331 [BOI2004]Sequence 数字序列
题意 大力猜结论. 首先将所有\(a_i\)变为\(a_i-i\),之后求不严格递增的\(b_i\),显然答案不变,最后\(b_i\)加上\(i\)即可. 考虑两种特殊情况: 1.\(a[]\)是递增 ...
- Luogu P4331 [BOI2004]Sequence 数字序列 (左偏树论文题)
清晰明了%%% Fairycastle的博客 个人习惯把size什么的存在左偏树结点内,这样在外面好写,在里面就是模板(只用修改update). 可以对比一下代码(好像也差不多-) MY CODE # ...
- 洛谷P4331[BOI2004] sequence
博客复活? 这个题很模板啊.随便上个左偏树.之前第一遍写对了.然后今天翻出来又写了一遍发现了一个奇奇怪怪的问题. 对比如下 上面的是AC 下面的WA 真的是一个很蠢的问题...你TM堆顶都弹出来了,堆 ...
- 洛谷$P4331\ [BOI2004]\ Sequence$ 数字序列 左偏树
正解:左偏树 解题报告: 传送门$QwQ$ 开始看到的时候$jio$得长得很像之前做的一个$dp$,,, 但是$dp$那题是说不严格这里是严格? 不难想到我们可以让$a_{i},b_{i}$同时减去$ ...
随机推荐
- [csp-201809-3]元素选择器-编译原理
声明:同样是参考照抄hyh学长的代码!(有问题我马上删这篇emm 题目链接:http://118.190.20.162/view.page?gpid=T77 题面: 这棵树的样子(同样是来自学长的图) ...
- 用java代码在创建hbase表时指定region的范围
package com.liveyc.common.utils; import java.util.List; import org.apache.hadoop.hbase.util.Bytes; i ...
- Tinyos Makerules解读
Makerules 文件解读 位于/opt/tinyos-2.1.2/support/make #-*-Makefile-*- vim:syntax=make #$Id: Makerules,v 1. ...
- 使用showplan.sql分析sql Performance
在HelloDBA网站找到一个分析sql性能的工具-showplan,记录一下 showplan.sql下载路径:http://www.HelloDBA.com/Download/showplan.z ...
- 如何删除git远程分支(转)
1,在开发过程中,大家在远程创建了许多分支,有些是无用的,该如何删除呢,可以参考下面的方法. 如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的 master 分支(或任何其他存放 稳 ...
- Integer类实现方式和注意事项
java.lang.Integer类的源代码: //定义一个长度为256的Integer数组 static final Integer[] cache = new Integer[-(-128) + ...
- java基础12 抽象类(及关键字:abstract)
抽象类:abstract 1.应用的场景 我们描述一类事物时,存在着某种行为,但这种行为目前不具体,那么我们就可以抽取这种行为的声明,但是不去实现这种行为,我们就需要使用抽象类. 2.抽象的好处 强制 ...
- Linux环境Nginx安装、调试以及PHP安装
linux版本:64位CentOS 6.4 Nginx版本:nginx1.8.0 php版本:php5.5 1.编译安装Nginx 官网:http://wiki.nginx.org/Install 下 ...
- html 简单学习
通过记事本,依照以下四步来创建您的第一张网页. 步骤一:启动记事本 如何启动记事本: 开始 所有程序 附件 记事本 步骤二:用记事本来编辑 HTML 在记事本 ...
- initialization 与 finalization 执行顺序 研究
看GIF: 第二个GIF: DEMO下载:http://files.cnblogs.com/files/del88/InitOrderDemo.zip