20211005省选组T1 数列(array)

链接

考虑对于一个点,能转移来的只有一条单调下降的序列和一条单调上升的序列。

那么我们直接用单调栈维护这两个,同时发现转移的形式是跟斜率优化类似的,套用斜率优化即可,对于一个序列在同一个单调栈上维护 \(a_i\) 的单调和斜率的单调。

注意两条链使用斜率优化时的符号不一样。

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#define ll __int128
#define db double
using namespace std;
const int N=1e6+10;
int n,m,a[N],la[N],q1[N],q2[N],r1,r2;
ll f[N],ans;
int b[N],tot=0;
ll sqr(ll a){return a*a;}
void write(ll ans){
	while(ans){
		b[tot++]=ans%10;
		ans/=10;
	}
	fd(i,tot-1,0)printf("%d",b[i]);
}
db calc(int x,int y){
	return (db)(f[x]-f[y] + sqr(a[x]) - sqr(a[y])) / (db)(a[x]-a[y]) / 2;
}
int main(){
	freopen("array.in","r",stdin);
	freopen("array.out","w",stdout);
	scanf("%d%d",&n,&m);
	fo(i,1,n)scanf("%d",&a[i]);
	r1=r2=1;
	q1[1]=q2[1]=1;
	fo(i,2,n){
		while(r1>1 && calc(q1[r1-1],q1[r1])>a[i])--r1;
		while(r2>1 && calc(q2[r2-1],q2[r2])<a[i])--r2;
		int t=q1[r1];
		f[i]=f[t] + m + sqr(a[i] - a[t]);
		t=q2[r2];
		f[i]=max(f[i],f[t] + m + sqr(a[i] - a[t]));
		ans=max(ans,f[i]);
		while(r1 && a[q1[r1]]<=a[i])--r1;
		while(r2 && a[q2[r2]]>=a[i])--r2;
		while(r1>1 && calc(q1[r1-1],q1[r1])>=calc(q1[r1],i))--r1;
		while(r2>1 && calc(q2[r2-1],q2[r2])<=calc(q2[r2],i))--r2;
		q1[++r1]=q2[++r2]=i;
	}
	write(ans);

	return 0;
}
上一篇:【10.6 牛客提高(二)】 【结论题】 串串串


下一篇:OSPF的不规则区域