BalticOI 2004 Sequence 题解
题目链接在这里~
对于序列\(\{a\}\),把每一个\(a_i\)减去一个\(i\),得到\(\{a'\}\)序列\(\{b\}\)同理。
因为\(b_1<b_2<...<b_n\),故\(b_1'\leqslant b_2'\leqslant ... \leqslant b_n'\)
又\(a_i-b_i\)不变,故新问题与原问题等价。
因此我们就把问题就转化成了一个单调不下降序列。
我们将\(\{a_1, a_2, ..., a_m\}\)序列分成两段\(a_1...a_n\)\(a_{n+1}...a_m\)
假设\(b_1=b_2=...=b_n=u,b_{n+1}=b_{n+2}=... = b_{m}=v\)
则这个问题就变成了经典的邮递员问题,即货仓选址问题。
分类讨论:
- \(u\leqslant v\),则前半段取\(u\),后半段取\(v\)即为最优解。
- \(u > v\),则\(\frac{u+v}{2}\)(\(u,v\)的中位数)为最优解,用左偏树实现。
得到了中位数之后还需要下压.
那么其中有两种情况. 奇数个数的中位数, 和偶数个数的中位数(为了方便用cost表示a和b的差值的绝对值):
1 奇数个数的中位数的时候就只能选这个中位数, 然后无论再往上或者往下压的cost都得增加至少1. 那么如果这个中位数的解如果不小于再往前一段的解的话, 则可以结束. 若小于, 则需要再往前合并找中位数循环直到结束
2 偶数个数的中位数. 那么可以在中间2个数之间上下浮动:
a. 如果再往前一段的解在这2个数之间, 则取再往前一段的解即可. 否则如果往上虽然不增加cost但是还能下压, 往下的话就得继续合并前一段增加cost.
b. 如果再往前一段的解小于这个区间, 则直接选这2个数里面小的即可
c. 如果再往前一段的解大于这个区间, 则还是选这2个数里面小的, 然后再往之前合并
code
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e6 + 10;
int n, v[N], dist[N], l[N], r[N], ans[N], tt;
ll res;
struct Segment{int end, root, size;}stk[N];
int merge(int x, int y)
{
if (!x || !y) return x + y;
if (v[x] < v[y]) swap(x, y);
r[x] = merge(r[x], y);
if (dist[r[x]] > dist[l[x]]) swap(r[x], l[x]);
dist[x] = dist[r[x]] + 1;
return x;
}
int pop(int x){return merge(l[x], r[x]);}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ )
{
scanf("%d", &v[i]);
v[i] -= i;
}
for (int i = 1; i <= n; i ++ )
{
auto cur = Segment({i, i, 1});
dist[i] = 1;
while (tt && v[cur.root] < v[stk[tt].root])
{
cur.root = merge(cur.root, stk[tt].root);
if (cur.size % 2 && stk[tt].size % 2) cur.root = pop(cur.root);
cur.size += stk[tt].size, tt -- ;
}
stk[ ++ tt] = cur;
}
for (int i = 1, j = 1; i <= tt; i ++ ) while (j <= stk[i].end) ans[j ++ ] = v[stk[i].root];
for (int i = 1; i <= n; i ++ ) res += abs(v[i] - ans[i]);
printf("%lld\n", res);
for (int i = 1; i <= n; i ++ ) printf("%d ", ans[i] + i);
return 0;
}
BalticOI 2004 Sequence 题解的更多相关文章
- luogu 4331 [BalticOI 2004]Sequence 数字序列
LINK:数字序列 这是一道论文题 我去看了一眼论文鸽的论文. 发现讲的还算能懂.可并堆的操作也讲的比较清晰. 对于这道题首先有一个小trick 我们给a数组全部减去其对应的下标这样我们求出来的b数组 ...
- 【CF486E】LIS of Sequence题解
[CF486E]LIS of Sequence题解 题目链接 题意: 给你一个长度为n的序列a1,a2,...,an,你需要把这n个元素分成三类:1,2,3: 1:所有的最长上升子序列都不包含这个元素 ...
- 题解-BOI 2004 Sequence
Problem bzoj & Luogu 题目大意: 给定序列\(\{a_i\}\),求一个严格递增序列\(\{b_i\}\),使得\(\sum \bigl |a_i-b_i\bigr|\)最 ...
- CF3D Least Cost Bracket Sequence 题解
题目 This is yet another problem on regular bracket sequences. A bracket sequence is called regular, i ...
- POJ3581:Sequence——题解
http://poj.org/problem?id=3581 给一串数,将其分成三个区间并且颠倒这三个区间,使得新数列字典序最小. 参考:http://blog.csdn.net/libin56842 ...
- BZOJ4355:Play with sequence——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4355 维护一个长度为N的序列a,现在有三种操作: 1)给出参数U,V,C,将a[U],a[U+1] ...
- Pop Sequence 题解
Pop Sequence(PAT) https://www.nowcoder.com/pat/5/problem/4090 前言: PAT上一道Stack的应用题,简化版的有<信息学一本通·普及 ...
- CF524F And Yet Another Bracket Sequence 题解
题目链接 算法:后缀数组+ST表+贪心 各路题解都没怎么看懂,只会常数巨大的后缀数组+ST表,最大点用时 \(4s\), 刚好可以过... 确定合法序列长度 首先一个括号序列是合法的必须满足以 ...
- 洛谷 P6573 [BalticOI 2017] Toll 题解
Link 算是回归OI后第一道自己写的题(考CSP的时候可没回归) 写篇题解纪念一下 题目大意: \(n\) 个点,\(m\) 条单向边,每条边的两端点 \(x\),\(y\)必定满足 \(\left ...
- Codeforces 486E LIS of Sequence 题解
题目大意: 一个序列,问其中每一个元素是否为所有最长上升子序列中的元素或是几个但不是所有最长上升子序列中的元素或一个最长上升子序列都不是. 思路: 求以每一个元素为开头和结尾的最长上升子序列长度,若两 ...
随机推荐
- 三种梯度下降法的对比(BGD & SGD & MBGD)
常用的梯度下降法分为: 批量梯度下降法(Batch Gradient Descent) 随机梯度下降法(Stochastic Gradient Descent) 小批量梯度下降法(Mini-Batch ...
- 状态估计和KalmanFilter公式的推导与应用
状态估计的概率解释 运动和观测方程: \[\left\lbrace \begin{array}{l} x_k = f(x_{k_1}, u_k) + w_k \\ z_k = h(y_j, x_k) ...
- C/C++ 知海拾遗
C语言知识拾遗 2022/11/11 memset()函数用法 包含头文件:<string.h> 作用:给任意类型变量数组初始化,即万能初始化函数. 使用形式:memset( void* ...
- SCI简介和写作顺序
一.SCI论文组成部分简介 一篇完整的 sci 论文主要包括以下几个主要的组成部分,从前往后依次分别是 Title 就是说这个文章的标题其次是 Abstract 也就是这个文章的摘要.接下来是 Int ...
- laravel的_token传值 ; header中传_token
laravel框架中只要是涉及到post传值都需要传 _token ,这是框架中为了防止crsf攻击所做的安全措施,那么我们用到ajax中的post 方式传值时,也需要在所传数据中添加一个_token ...
- Go语言核心36讲35
到目前为止,我们已经一起学习了Go语言标准库中最重要的那几个同步工具,这包括非常经典的互斥锁.读写锁.条件变量和原子操作,以及Go语言特有的几个同步工具: sync/atomic.Value: syn ...
- swap,传参实质
void swap(int a,int b){ int s=a; a=b; b=s; } int main(){ int x=1,y=2; swap(x,y); } 上面的函数并不能实现交换,因为传参 ...
- SpringCLoud_Aibaba
微服务项目核心组件 https://gitee.com/gtnotgod/spring-cloud_-alibaba_-study001.git 注册中心:nacos API网关:gateway 生产 ...
- php7怎么安装memcache扩展
php7安装memcache扩展 1.下载文件,解压缩 memcache windows php7下载地址: https://github.com/nono303/PHP7-memcache-dll ...
- Oracle 一对多将多行数据整理为一行
在开发中一对多的关系经常用到,昨天遇到一个客户问题,要求将所有反馈任务的信息整理为一行展示并导出excel. 我数据库对应关系:通任务task对应feedback表多个反馈,也就是说每个任务都有很多条 ...