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;
    }
    
  • 相关阅读:
    private static final long serialVersionUID = 1L;
    HashMap和Hashtable的区别
    MySQL中tinytext、text、mediumtext和longtext详解
    char、varchar、text和nchar、nvarchar、ntext的区别
    java获取文件夹下文件名
    java删除文件
    js判断浏览器
    nodejs调试:node-inspector
    [转]各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT
    [IBM]掌握Ajax,Ajax中的高级请求和响应
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14513570.html
Copyright © 2011-2022 走看看