牛客网 求最大值( 思维 )

题目链接

题意 : 给出一个序列,你的任务是求每次操作之后序列中 (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
", (--mp.end())->first);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/qwertiLH/p/8018168.html