题意 : 给出一个序列,你的任务是求每次操作之后序列中 (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; }