Yxy7952
2024-11-20 16:23:12
现在有一个
注意:第一个数已经作为 BST 的根。
暴力模拟肯定会超时,根据二叉搜索树的性质:
设第
i 个节点的权值x ,则其左子树中的权值都小于x ,右子树中的权值都大于x 。
思考一下可以发现我们每次只需要找到小于第
因为单调栈刚好可以处理这种问题(找到某个数的左右边比它大/小的最近的数),所以可以考虑用它解决这道题。又由于
注意:由于找第
干完这一切之后,发现计数器跟深度(从这个节点到根节点的最长路径)有关系,所以只需处理它的深度并输出即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=500005;
int i,top,n,stck[maxn],id[maxn],a[maxn],L[maxn],R[maxn],dep[maxn];
long long ans=0;
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n;
for(i=1;i<=n;i++) cin>>a[i],id[a[i]]=i; //id[i]:数i的位置
a[0]=id[0]=top=stck[top]=0;
for(i=n;i>=1;i--){//按数值从大到小处理,位置入栈,
while(top>=0){
if(stck[top]>id[i]) top--;
else break;
}
R[i]=a[stck[top]];
stck[++top]=id[i];
}
top=0;
dep[0]=-1;
for(i=1;i<=n;i++){//按数值从小到大处理,位置入栈
while(top>=0){
if(stck[top]>id[i]) top--;
else break;
}
L[i]=a[stck[top]];
stck[++top]=id[i];
}//栈里的位置值从小到大
for(i=1; i<=n; i++) {
dep[a[i]]=1+max(dep[L[a[i]]],dep[R[a[i]]]);
ans=ans+dep[a[i]];
cout<<ans<<"\n";
}
return 0;
}