把数组排序,那么其中连续的一段一定是树里边一颗子树
那么我们把那一段最先插入的点找出来最为子树的根,然后分成两颗树继续往下递归
具体查最先插入方法用ST表就可以了
c o d e code code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
long long n;
long long dep[301000], f[301010][32], b[301010];
struct node
{
long long x, id;
}a[301010];
bool cmp(node x, node y)
{
return x.x<y.x;
}
void dfs(long long l, long long r, long long d)
{
if(l>r)
return;
long long k=log2(r-l+1);
long long x=min(f[l][k], f[r-(1<<k)+1][k]);
dep[x]=d;
dfs(l, b[x]-1, d+1);
dfs(b[x]+1, r, d+1);
}
int main()
{
scanf("%lld", &n);
for(long long i=1; i<=n; i++)
scanf("%lld", &a[i].x), a[i].id=i;
sort(a+1, a+1+n, cmp);
for(long long i=1; i<=n; i++)
f[i][0]=a[i].id, b[a[i].id]=i;
for(long long j=1; j<=log2(n); j++)
for(long long i=1; i+(1<<j)-1<=n; i++)
f[i][j]=min(f[i][j-1], f[i+(1<<j-1)][j-1]);
dfs(1, n, 0);
long long sum=0;
for(long long i=1; i<=n; i++)
{
sum+=dep[i];
printf("%lld\n", sum);
}
return 0;
}