牛客网 求最大值( 思维 )

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客网 求最大值( 思维 )相关的知识,希望对你有一定的参考价值。

题目链接

题意 : 给出一个序列,你的任务是求每次操作之后序列中 (a[j]-a[i])/(j-i)【1<=i<j<=n】的最大值。操作次数有Q次,每次操作需要将位子p处的数字变成y.

 

分析 : 最大值实际上只要考虑相邻的 i 和 j 就行了,即相邻的a[]数组元素,此时式子的分母永远是 1 ,为什么?简单地看看这个式子 ( a[j] - a[i] ) / ( j - i ) ,先看其分子,如果此时 i 和 j 不是相邻的,那么对于 i < j 来说我们总能够用 i ~ j 中( j - i )个相邻的元素来拼成 a[j] - a[i] ,例如 a[3] - a[1] 实际就是 [ ( a[3] - a[2] ) + ( a[2] - a[1] ) ] / (3 -2) 其他的类似,那么也就是说如果去考虑不相邻的 i 和 j 那么得到的肯定是一系列 ( j - i 个 ) 相邻的元素差值的平均值,肯定不可能是最大的!所以我们只要考虑相邻的 i 和 j 即可!实现方式可以使用 map 键值存储差值、value存储数量,对于每一次操作如果value==0则erase掉,然后更新,最后的答案就是(--map.end())->first。也可以使用线段树,代码量会多一点,但是更快

 

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int arr[maxn];
int main(void)
{
    int n;
    while(~scanf("%d", &n)){

        map<int, int> mp;
        mp.clear();

        for(int i=1; i<=n; i++){
            scanf("%d", &arr[i]);
            //if(i!=1) mp[arr[i] - arr[i-1]]++; //只有一个元素就错了!
        }
        for(int i=1; i<n; i++)
            mp[arr[i+1] - arr[i]]++;

        int Query;
        scanf("%d", &Query);
        while(Query--){
            int pos, val;
            scanf("%d %d", &pos, &val);
            if(pos != 1){
                if(--mp[arr[pos] - arr[pos-1]]==0)
                    mp.erase(arr[pos] - arr[pos-1]);
            }
            if(pos != n){
                if(--mp[arr[pos+1] - arr[pos]]==0)
                    mp.erase(arr[pos+1] - arr[pos]);
            }
            arr[pos] = val;
            if(pos != 1) mp[arr[pos] - arr[pos-1]]++;
            if(pos != n) mp[arr[pos+1] - arr[pos]]++;
            printf("%d.00\n", (--mp.end())->first);
        }
    }
    return 0;
}
View Code

 

以上是关于牛客网 求最大值( 思维 )的主要内容,如果未能解决你的问题,请参考以下文章

牛客网:连续子数组的最大和(动态递归解法)

牛客网Nowcoder 牛客练习赛13 A.幸运数字Ⅰ B.幸运数字Ⅱ(数组或者dfs) C.幸运数字Ⅲ(思维)

牛客网-颜料的混合思维

牛客网 珂朵莉与宇宙(思维)

牛客网NOIP赛前集训营-提高组(第四场)B 区间(单调优化)

牛客网NOIP赛前集训营-提高组(第四场)B 区间(单调优化)