洛谷堆+结论P4597 序列sequence

Posted DEVILK

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷堆+结论P4597 序列sequence相关的知识,希望对你有一定的参考价值。

【题目背景:】

原题cf13c 数据加强版(就是说原来能用DP做现在不行了QwQ)

【题目描述:】

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

【输入格式:】

第一行输入一个n,表示有n( n \leq 5*10^5n5?105 )个数字。第二行输入n个整数,整数的绝对值不超过 10^9109

【输出格式:】

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

 

【算法分析:】

切题背景:
chen_zhe大佬改编了这道题目之后吸引了slyz准高一全机房同学的注意

主要是一开始是道紫题想要通过以后强行把它变黑(雾

然后全机房的同学刚了一节课4597无果(中间它突然变成了黑题QwQ)

然后就被隔壁机房的学长学姐拯救了...

 

自己想的证明:

对于一个序列,可以看成高度不同的几根线

如:序列{3、 4、 1、 5}可以看做这样

 

技术分享图片
                  ----                
     ----
---- 
          
            ----
3 4 1 5

 

对于一个大数a和一个小数b,要做的就是在他们之间的任意位置找到一个基准,将大数向下挪到那个基准,小数向上挪到那个基准

移动的距离等价于a - b

由于是非降序列,将a向下移动的距离越多越可以使之后的数字更容易变成非降序列

所以这个基准应该是选择之前的最小数c,而之前的最小数一定是在[a, b]这个区间内,将a向下移到c并将b向上移到c的距离等价于将a向下移动到b的距离

所以就把a移到b就好了

 

然后开个大根堆瞎搞:

对于读进的一个数num,把它push到优先队列里去

如果这个num比之前的最大值maxn(就是堆顶元素)要小的话

  ans += maxn - num

  并把maxn弹出,再push进一个num(把maxn移动到了num的位置)

 

【代码:】

 1 //序列sequence加强版
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 
 8 int n;
 9 long long ans;
10 priority_queue<int> q;
11 
12 inline int read() {
13     int x = 0, f = 1; char ch = getchar();
14     while(ch < 0 || ch > 9) { if(ch == -) f = -1; ch = getchar(); }
15     while(ch >= 0 && ch <= 9)
16         x = (x << 3) + (x << 1) + ch - 48, ch = getchar();
17     return x * f;
18 }
19 
20 int main() {
21     n = read();
22     for(int i = 1; i <= n; i++) {
23         int num = read();
24         q.push(num);
25         if(num < q.top()) {
26             ans += q.top() - num;
27             q.pop();
28             q.push(num);
29         }
30     }
31     printf("%lld\n", ans);
32 }

 


以上是关于洛谷堆+结论P4597 序列sequence的主要内容,如果未能解决你的问题,请参考以下文章

P4597 序列sequence

洛谷堆+贪心P1484 种树

洛谷堆P1801 黑匣子_NOI导刊2010提高(06)

2018山东省赛 E Sequence ( 思维 )

2019.01.19-2018年6月NEYC集训sequence

drf框架 2 drf框架的请求生命周期(as_view和dispatch方法), 请求解析渲染响应异常, 序列化组件 ,ORM配置回顾(media文件配置),应用在settings.py中(代码片