Jzoj5236 利普希茨

对于一个整数序列A,我们定义f(A)=max{floor(|Ai-Aj|/(j-i))},这里i<j

给出一个长度为n的序列A,有q此操作

1.修改一个元素的值

2.询问A的一段区间[l,r]组成的序列的f(A[l..r])

这里有一个很显然的结论,那就是使得f取到最大的i,j一定满足j=i+1

为什么?可以证明一下,以下证明来自jefflyy:函数

"

用归纳法,若(长度为2⋯n的序列的答案)都由长度为2的子序列产生,我们将要证明:长度为n+1的序列答案也由长度为2的子序列产生

设它是a1⋯n+1,若答案为它本身而不是其他子序列,那么a1an+1一个是最小一个是最大,不妨设a1<an+1

那么这个序列的Lipshitz常数为an+1−a1n,因为其他长度的子序列的答案都由长度为2的子序列产生,那么对1≤i≤n,都有an+1−a1n>|ai−ai+1|

把这n个不等式加起来,得an+1−a1>|a1−a2|+⋯+|an−an+1|

整理,得a2+|a2−a3|+⋯+|an−1−an|−an<0

移一下绝对值外的,再补上几项,得an−an−1+⋯+a3−a2>|an−an−1|+⋯+|a3−a2|

一个数取绝对值后不会变小,所以这里显然矛盾,原命题得证

因为长度为2的序列的答案显然长度为2,所以对于任意n≥2,长度为n的序列,答案都由长度为2的子序列产生

"

证明完了,我们就可以用差分+线段树乱搞了233333333

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int w[100010],s[400040],n,m;
inline void update(int l,int r,int x,int p,int k){
	if(l==r){ s[x]=k; return ; }
	int m=l+r>>1;
	if(p<=m) update(l,m,x<<1,p,k);
	else update(m+1,r,x<<1|1,p,k);
	s[x]=max(s[x<<1],s[x<<1|1]);
}
inline int query(int l,int r,int x,int L,int R){
	if(L<=l && r<=R){ return s[x]; }
	int m=l+r>>1,ans=0;
	if(L<=m) ans=max(ans,query(l,m,x<<1,L,R));
	if(m<R) ans=max(ans,query(m+1,r,x<<1|1,L,R));
	return ans;
}
int main(){
	freopen("lipschitz.in","r",stdin);
	freopen("lipschitz.out","w",stdout);
	scanf("%d%d",&n,w); 
	for(int i=1;i<n;++i) scanf("%d",w+i),update(1,n,1,i,abs(w[i]-w[i-1]));
	scanf("%d",&m);
	for(int a,b,c,i=0;i<m;++i){
		scanf("%d%d%d",&a,&b,&c);
		if(a) printf("%d
",query(1,n,1,b,c-1));
		else { w[b-1]=c; update(1,n,1,b,abs(w[b]-w[b-1])); if(b>1) update(1,n,1,b-1,abs(w[b-1]-w[b-2])); }
	}
}

原文地址:https://www.cnblogs.com/Extended-Ash/p/7887163.html