NC14402-求最大值
- 链接: NC14402最大值
- 题意:一个初始序列,可进行操作。每次操作将位置x处的数字变成y,操作之后输出
max
(
a
j
−
a
i
j
−
i
)
(
1
≤
i
<
j
≤
n
)
\max(\frac{a_j-a_i}{j-i})(1≤i <j≤n)
max(j−iaj−ai)(1≤i<j≤n)
- 差分、线段树
- 将
a
i
a_i
ai看坐坐标系上的点
(
i
,
a
i
)
(i,a_i)
(i,ai),那么
a
j
−
a
i
j
−
i
\frac{a_j-a_i}{j-i}
j−iaj−ai就可看作斜率
k
k
k,问题就转化为求坐标轴上n个点上的最大斜率
- 显然相邻两点斜率最大,因此差分数组,线段树维护差分数组的最大值即可
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 200005;
int n;
int a[maxn];
int tr[maxn<<2];
void build(int rt,int l,int r)
{
if(l == r){tr[rt] = a[l+1]-a[l]; return; }
int mid = (l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
tr[rt] = max(tr[rt<<1],tr[rt<<1|1]);
}
void update(int rt,int l,int r,int x)
{
if(l == r) { tr[rt] = a[x+1]-a[x]; return; }
int mid = (l+r)>>1;
if(x<=mid) update(rt<<1,l,mid,x);
else update(rt<<1|1,mid+1,r,x);
tr[rt] = max(tr[rt<<1],tr[rt<<1|1]);
}
int main()
{
while(~scanf("%d",&n))
{
for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
build(1,1,n-1);
int q; scanf("%d",&q);
for(int i = 1; i <= q; i++)
{
int x,y;
scanf("%d%d",&x,&y); a[x] = y;
if(x != n)
update(1,1,n-1,x);
if(x != 1)
update(1,1,n-1,x-1);
printf("%.2lf\n",1.0*tr[1]);
}
}
return 0;