• 【洛谷】【堆+结论】P4597 序列sequence


    【题目背景:】

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

    【题目描述:】

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

    【输入格式:】

    第一行输入一个n,表示有n( n leq 5*10^5n5105 )个数字。第二行输入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就好了

      而由于之前已经有一个c值,不把a,b移动到c也能保证之后答案的正确性

        而当之后如果有许多个小数的时候,这么做也能保证之后答案的正确性,因为当前的c和当前b在这种情况里应该是同属于[之后的a, 之后的b]的区间内

    当之前的最大数比b还要小的时候,b就变成了之前非降序列的一部分,a - b相当于将a向下移动到b

    由于c是之前的最大数(也就是说现在的a > c),所以不存在c比a大的情况

    然后开个大根堆瞎搞:

    对于读进的一个数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
    ", ans);
    32 }
  • 相关阅读:
    leetcode-滑动窗口
    leetcode刷题-双指针
    nlp
    机器学习
    tf-idf算法
    RNN和LSTM的理解
    DDD落地实践-战术实现心得
    DDD落地实践-战略设计心得
    测试平台系列(66) 数据驱动之基础Model
    Python小知识之对象的比较
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9038078.html
Copyright © 2020-2023  润新知