UOJ246 【UER7】 套路

Description

定义区间权值的 s(l,r) 表示 minlx<yr{|axay|}

给定序列 a,求最大的 s(l,r)(rl)

n2×105,1ai2×105

Solution

s(l,r) 可以通过 DP 得到:s(l,r)=min{s(l,r1),s(l+1,r),|alar|}

全题的 Key observation 由抽屉原理得到: s(l,r)mrl+1

那么使用根号分治来做:

  • 对于区间长度 n 的部分按照上面的 DP 式子暴力求 s(l,r) 在更新答案

  • 对于区间长度比较大的部分,可以枚举 s 的数值,对于每个右端点计算满足条件的最小左端点

    对于当前枚举的 s=v,设 posi 表示最小的满足 s(posi,i)=v 的位置,转移给 s=v+1 可以通过消去差为 v 的位置,即 posi=max{posi1,appaiv,appai+v}

时间复杂度 Θ(nm)

Code

const int N=2e5+10,B=500;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m,K,a[N],S[N],lef[N],app[N];
signed main(){
	n=read(); m=read(); K=read();
	rep(i,1,n) a[i]=read(),S[i]=inf;
	int ans=0;
	for(int len=1;len<=B;++len){
		for(int i=1;i<=n-len;++i){
			ckmin(S[i],min(S[i+1],abs(a[i]-a[i+len])));
			if(len>=K-1) ckmax(ans,len*S[i]);		
		}
	}
	rep(j,0,B) lef[j]=1;
	for(int i=1;i<=n;++i){
		for(int j=0;j<=B;++j){
			if(i-lef[j]+1>=K) ckmax(ans,j*(i-lef[j]));
			ckmax(lef[j+1],lef[j]);
			if(a[i]+j<=m) ckmax(lef[j+1],app[a[i]+j]+1);
			if(a[i]-j>=1) ckmax(lef[j+1],app[a[i]-j]+1);
		}
		app[a[i]]=i;
	}
	print(ans);
	return 0;
}
posted @   没学完四大礼包不改名  阅读(138)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示