之前用的单调栈解决的,这次发现了一个新方法 笛卡尔树,记录一下
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=100005;
int n,a[maxn],ls[maxn],rs[maxn],fa[maxn],stk[maxn],top=0,sum[maxn];
long long ans;
inline int read(){
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline void DFS(int x){
if (x<1||x>n) return;
if ((long long)(sum[ls[x]]+sum[rs[x]]+1)*(long long)a[x]>ans) ans=(long long)(sum[ls[x]]+sum[rs[x]]+1)*(long long)a[x];
sum[x]=sum[ls[x]]+sum[rs[x]]+1;
DFS(fa[x]);
}
int main(){
n=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++){
if (a[i]>=a[stk[top]]||top==0){
rs[stk[top]]=i;
fa[i]=stk[top];
stk[++top]=i;
} else {
while (a[stk[top]]>a[i]&&top>=1) top--;
rs[stk[top]]=i;fa[i]=stk[top];
ls[i]=stk[top+1];fa[stk[top+1]]=i;rs[i]=0;
stk[++top]=i;
}
}
for (int i=1;i<=n;i++) if (ls[i]==0&&rs[i]==0) DFS(i);
printf("%lld\n",ans);
return 0;
}
笛卡尔树求最大子段和

本文介绍了一种使用笛卡尔树解决最大子段和问题的新方法,通过构建笛卡尔树并进行深度优先搜索(DFS),实现了比单调栈更优的算法。代码中详细展示了如何构建笛卡尔树,更新节点的左右子树、父节点和子树的和,并通过DFS遍历树来找到最大子段和。
192

被折叠的 条评论
为什么被折叠?



