题目描述
给出一个序列,你的任务是求每次操作之后序列中 (a[j]-a[i])/(j-i)【1<=i<j<=n】的最大值。
操作次数有Q次,每次操作需要将位子p处的数字变成y.
输入描述:
本题包含多组输入,每组输入第一行一个数字n,表示序列的长度。
然后接下来一行输入n个数,表示原先序列的样子。
再接下来一行一个数字Q,表示需要进行的操作的次数。
最后Q行每行两个元素p,y,表示本操作需要将位子p处的数字变成y.
数据范围:
3<=n<=200000
1<=Q<=200000
-1000000000<=a[i]<=1000000000
输出描述:
每组数据输出Q行,每行输出一个浮点数,保留两位小数,表示所求的最大值。
示例1
输入
复制

5
2 4 6 8 10
2
2 5
4 9
输出
复制

3.00
3.00
说明
第一次操作之后的序列变成:2 5 6 8 10
第二次操作之后的序列变成:2 5 6 9 10


我们可以看出式子的几何意义即表示线段的斜率。

然后我们通过画图可以得知,斜率最大值,必然是出现在相邻的两项之间,不然我们随便取一点与两个端点相连,必然能产生更大的斜率。

所以我们维护以每个点开始,与后面那个点的斜率即可。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5;
int n,q,a[N];
struct node{
	int l,r,mx;
}t[N<<2];
inline void push_up(int p){
	t[p].mx=max(t[p<<1].mx,t[p<<1|1].mx);
}
void build(int p,int l,int r){
	t[p].l=l; t[p].r=r;
	if(l==r)	return void(t[p].mx=a[l+1]-a[l]);
	int mid=l+r>>1;
	build(p<<1,l,mid);	build(p<<1|1,mid+1,r);
	push_up(p);
}
void change(int p,int x,int v){
	if(t[p].l==t[p].r){
		t[p].mx=v; return ;
	}
	int mid=t[p].l+t[p].r>>1;
	if(x<=mid)	change(p<<1,x,v);
	else	change(p<<1|1,x,v);
	push_up(p);
}
signed main(){
	while(cin>>n){
		for(int i=1;i<=n;i++)	scanf("%d",&a[i]);
		cin>>q; build(1,1,n-1);
		while(q--){
			int p,y;	scanf("%d %d",&p,&y);	a[p]=y;
			if(p!=n)	change(1,p,a[p+1]-y);	
			if(p!=1)	change(1,p-1,a[p]-a[p-1]);
			printf("%d.00\n",t[1].mx);
		}
	}
	return 0;
}