P4597 序列sequence

题目背景

原题\(\tt{cf13c}\)数据加强版

题目描述

给定一个序列,每次操作可以把某个数\(+1\)或\(-1\)。要求把序列变成非降数列。而且要求修改后的数列只能出现修改前的数。

输入输出格式

输入格式:

第一行输入一个\(n\),表示有\(n(n \leq 5\times10^5)\)个数字。

第二行输入\(n\)个整数,整数的绝对值不超过\(10^9\)

输出格式:

输出一个数,表示最少的操作次数


发现之前洛谷做过一个类似的。。P2893

chen_zhe的题解并没有看懂。

原题的\(N^2\)思路比较好想,离散化后直接开到状态里面就可以了。

然后维护一个按时间顺序维护一个完整的非降数列,假设当前维护到位置\(i\)了

当前数列的末尾为\(p\)

  • 若\(p\le a_i\)

    直接加入数列

  • 若\(p>a_i\)

    则把\(p\)和\(a_i\)作为一个二元组\((a_i,p)\)拿出来,那么一定要花\(a_i-p\)的代价让这个二元组变得不降

    如果不考虑其他情况,那么这个二元组可以取到的值为\((a_i,a_i),(a_i+1,a_i+1),\dots ,(p,p)\)

    显然取到最小值最好,那么我们就当\(\tt{Ta}\)取到了最小值,然后把\(\tt{Ta}\)的最小值放到数列。虽然这时候可能比现在的末尾要小,不过没关系,现在的新末尾也可能会改变。我们就当这个二元组在末尾大于\(\tt{Ta}\)的最小取值的时候,把\(\tt{Ta}\)当末尾那么大就可以了。

可以简单的拿一个大根堆维护上述过程。

考虑为什么这样一定可以取到修改前的数,其实也很好理解,毕竟我们二元组取值要么是自己,要么就是某个末尾啊。


Code:

#include <cstdio>
#include <queue>
#define ll long long
std::priority_queue <ll> q;
ll ans=0,a;int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a);
if(!q.empty()&&q.top()>a)
{
ans+=q.top()-a;
q.pop();
q.push(a);
}
q.push(a);
}
printf("%lld\n",ans);
return 0;
}

2018.11.7

最新文章

  1. 计算机视觉之《OpenCV开发环境搭建》
  2. ThinkPHP配置简单的mysql读写分离
  3. hdu4087ALetter to Programmers(三维旋转矩阵)
  4. git log --stat常用命令
  5. 自动布局(Masonry)设置tabbar
  6. (转)C# DES
  7. VellCar(barracuda buggy)
  8. 平衡搜索树(一) AVL树
  9. 非UI线程和UI线程通信
  10. MySql命令——函数
  11. [Swust OJ 797]--Palindromic Squares(回文数水题)
  12. PHP学习之-1.3 echo语句
  13. Java中判断是否为空的方法
  14. 微信小程序代码大全 - 小程序开发福利
  15. Java-this
  16. mysql多线程插入速度与不同数据库之间的比较
  17. 写vue项目时候 零星的笔记
  18. django 自动化测试的故障排查
  19. 伪ajax操作
  20. CSS Fonts(字体)

热门文章

  1. Oracle 字段拆分替换在合并成一条
  2. Qt 解析EXcel文件
  3. 适配chrome65最新selenium-chromedriver
  4. lintcode433 岛屿的个数
  5. 基于物品的协同过滤算法(ItemCF)
  6. geth账户密码
  7. hive创建外部表
  8. Python中如何Getting Help
  9. LintCode-71.二叉树的锯齿形层次遍历
  10. IPReversePathFilter