考虑如何建树。按顺序加入点,那么新点要不然是前驱的右儿子,要不然是后继的左儿子,否则权值在新点和它父亲中间的点只能做新点的儿子,而这是不可能的。而这两个节点,后插入的一定把先插入的那个位置占掉了,这样新点的插入位置就是惟一的。找前驱后继可以用平衡树维护。
建好树以后就是动态点分治裸题了。
#include<cstdio>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=200010;
int a[maxn],lson[maxn],rson[maxn],pos[maxn],dep[maxn],mnd[maxn][20],lg[maxn],
size[maxn],fa[maxn],val[maxn],vis[maxn],
n,clo,R;
LL sum[maxn],sumfa[maxn],ans;
vector<int> to[maxn];
set<int> s;
void dfs0(int u,int fa)
{
mnd[pos[u]=++clo][0]=dep[u];
for (int v:to[u])
if (v!=fa)
{
dep[v]=dep[u]+1;
dfs0(v,u);
mnd[++clo][0]=dep[u];
}
}
int dfs2(int u,int fa,int S)
{
int ret=-1,x;
val[u]=0;
size[u]=1;
for (int v:to[u])
if (!vis[v]&&v!=fa)
{
x=dfs2(v,u,S);
if (ret==-1||val[x]<val[ret]) ret=x;
size[u]+=size[v];
val[u]=max(val[u],size[v]);
}
val[u]=max(val[u],S-size[u]);
if (ret==-1||val[u]<val[ret]) ret=u;
return ret;
}
void dfs3(int u,int fa)
{
size[u]=1;
for (int v:to[u])
if (!vis[v]&&v!=fa)
{
dfs3(v,u);
size[u]+=size[v];
}
}
int dfs1(int u,int S)
{
int r=dfs2(u,-1,S),r1;
vis[r]=1;
dfs3(r,-1);
for (int v:to[r])
if (!vis[v])
{
r1=dfs1(v,size[v]);
fa[r1]=r;
}
vis[r]=0;
return r;
}
int dis(int u,int v)
{
int x=pos[u],y=pos[v],k;
if (x>y) swap(x,y);
k=lg[y-x+1];
return dep[u]+dep[v]-2*min(mnd[x][k],mnd[y-(1<<k)+1][k]);
}
void add(int u)
{
int d;
for (int i=u,j=0;i;j=i,i=fa[i])
ans+=sum[i]-sumfa[j]+(LL)dis(u,i)*(size[i]-size[j]);
for (int i=u,j=0;i;j=i,i=fa[i])
{
d=dis(u,i);
sum[i]+=d;
if (j) sumfa[j]+=d;
size[i]++;
}
}
int main()
{
//freopen("e.in","r",stdin);
set<int>::iterator it;
scanf("%d",&n);
scanf("%d",&a[1]);
s.insert(a[1]);
for (int i=2;i<=n;i++)
{
scanf("%d",&a[i]);
it=s.upper_bound(a[i]);
if (it==s.end()||lson[*it]) rson[*(--it)]=a[i];
else lson[*it]=a[i];
s.insert(a[i]);
}
for (int i=1;i<=n;i++)
{
if (lson[i]) to[i].push_back(lson[i]),to[lson[i]].push_back(i);
if (rson[i]) to[i].push_back(rson[i]),to[rson[i]].push_back(i);
}
dfs0(1,-1);
for (int k=1;(1<<k)<=clo;k++) lg[1<<k]=k;
for (int i=3;i<=clo;i++)
if (!lg[i]) lg[i]=lg[i-1];
for (int k=1;k<=lg[clo];k++)
for (int i=1;i+(1<<k)-1<=clo;i++)
mnd[i][k]=min(mnd[i][k-1],mnd[i+(1<<(k-1))][k-1]);
R=dfs1(1,n);
for (int i=1;i<=n;i++) size[i]=0;
for (int i=1;i<=n;i++)
{
add(a[i]);
printf("%lld\n",ans);
}
}