zoukankan      html  css  js  c++  java
  • 积木大赛(差分)

    题意

    (n)个积木,给定它们的高度(h_i),每次可以将某一段区间中的所有高度减一,问最少操作多少次可以将所有高度变成(0)

    数据范围

    (1 leq n leq 10^5)
    (0 leq h_i leq 10000)

    思路

    构造差分序列:

    [b_1 = a_1 \ b_2 = a_2 - a_1 \ b_3 = a_3 - a_2 \ dots \ b_n = a_n - a_{n - 1} \ b_{n + 1} = -a_n ]

    若原序列全都变为(0),那么差分序列也全变成了(0)。因此原问题等价于每次从 (b_1,b_2,dots ,b_{n+1})中挑两个数,前一个减(1),后一个加(1),多少次操作可以将差分序列全变成(0)

    对于差分序列中每个正数 (b_i),要将其减为(0),最少需要操作 (b_i)次,因此总操作次数一定不少于差分数组中所有正数之和 (B)

    然后我们能够构造一种操作方式,使得恰好可以通过 (B) 次操作,将所有数变成(0)。 那么就可以说明最少操作次数一定是所有正数之和。

    操作方式为:从后往前遍历,找到第一个整数,对其进行减(1)操作,其后必存在一个负数,对其进行加(1)操作。

    对于每个正数(b_i),其后必存在一个负数,原因是对(b_i)及其往后的数字求和得到的是(-a_k < 0),因此必存在负数。

    因此,最终答案就是差分数组中所有正数之和。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 100010;
    
    int n;
    int a[N];
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
        int ans = 0;
        for(int i = 1; i <= n; i ++)
            if(a[i] > a[i - 1])
                ans += (a[i] - a[i - 1]);
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    《构建之法》阅读报告
    教务管理系统类图及数据库E/R图
    设计模式:抽象工厂
    结对项目:四则运算程序测试
    Leetcode笔记之57和为s的连续正数序列
    Leetcode笔记之1103分糖果 II
    Leetcode笔记之199二叉树的右视图
    每日Scrum(9)
    每日Scrum(7)
    每日Scrum(6)
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14513570.html
Copyright © 2011-2022 走看看