一个初始为空的二叉搜索树T,以及1到N的一个排列P: {a1, a2, ..., aN}。我们向这个二叉搜索树T添加这些数,从a1开始, 接下来是 a2, ..., 以aN结束。在每一个添加操作后,输出T上每对节点之间的距离之和。
例如:4 7 3 1 8 2 6 5。最终的二叉树为:
4
/ \
3 7
/ / \
1 6 8
\ /
2 5
节点两两之间的距离和 = 6+5+5+4+3+2+1+5+4+4+3+2+1+4+3+3+2+1+3+2+2+1+2+1+1+2+1+3 = 76
Input
第1行:1个数N。(1 <= N <= 100000) 第2 - N + 1行:每行1个数,对应排列的元素。(1 <= ai <= N)
Output
输出共N行,每行1个数,对应添加当前元素后,每对节点之间的距离之和。
用set维护一下空的左右孩子位置和已插入的点可以O(nlogn)建树
然后就每加入 √(n) 个点重新树形dp一次,每加入一个点时和之前已加入但未dp的点间求距离,并计算和已dp的点对答案的贡献。
总复杂度O(n√(n)logn)
读入优化t了4个点,读入+输出优化t了1个点,fread+fwrite才a。。
#include<stdio.h> #include<set> #include<cmath> const int N=100007; char buf[2000003],*ptr=buf,rbuf[1000003],*rptr=rbuf-1; inline int _(){ int x=0,c=*++rptr; while(c<48)c=*++rptr; while(c>47)x=x*10+c-48,c=*++rptr; return x; } inline void _(long long x){ static int stk[32],stp=0; if(!x)stk[stp++]=0; while(x)stk[stp++]=x%10,x/=10; while(stp)*ptr++=stk[--stp]+48; *ptr++=10; } int n,pv=0; std::set<int>le,re,in; int ch[N][2],xs[N],dep[N],fa[N],sz[N],pf[N],top[N]; long long F1[N],F2[N],ans=0,ANS[N]; int _sz[N],h[N],tp[N]; inline int dis(int x,int y){ int a=top[x],b=top[y],s=dep[x]+dep[y]; while(a!=b){ if(dep[a]<dep[b])y=fa[b],b=top[y]; else x=fa[a],a=top[x]; } s-=dep[dep[x]<dep[y]?x:y]<<1; return s; } void rebuild(){ ans=0; for(int i=pv-1;~i;--i){ int w=xs[i],lc=ch[w][0],rc=ch[w][1]; h[w]=0; _sz[w]=1+_sz[lc]+_sz[rc]; F1[w]=_sz[w]-1+F1[lc]+F1[rc]; } for(int i=0;i<pv;++i){ int w=xs[i],lc=ch[w][0],rc=ch[w][1],s=_sz[rc]-_sz[lc]; F2[lc]=pv+s+F2[w]+F1[rc]; F2[rc]=pv-s+F2[w]+F1[lc]; F1[w]+=F2[w]; ans+=F1[w]; } ans>>=1; } int main(){ rbuf[fread(rbuf,1,1000000,stdin)]=0; n=_(); xs[0]=_(); le.insert(xs[0]); re.insert(xs[0]); in.insert(xs[0]); for(int i=1;i<n;++i){ int x=xs[i]=_(); in.insert(x); auto it=le.upper_bound(x); if(it!=le.end()){ auto it2=in.upper_bound(x); if(it2!=in.end()&&*it2==*it){ ch[fa[x]=*it][0]=x; le.erase(it); le.insert(x),re.insert(x); continue; } } it=re.upper_bound(x); --it; ch[fa[x]=*it][1]=x; re.erase(it); le.insert(x),re.insert(x); } for(int i=0;i<n;++i){ int w=xs[i]; dep[w]=dep[fa[w]]+1; } for(int i=n-1;~i;--i){ int w=xs[i]; int sl=sz[ch[w][0]],sr=sz[ch[w][1]]; sz[w]=1+sl+sr; pf[w]=ch[w][sl<sr]; } for(int i=0;i<n;i++){ int w=xs[i]; if(!top[w])for(int u=w;u;u=pf[u])top[u]=w; } int B=std::sqrt(n)/1.2+1; for(int i=0;i<n;++i){ int w=xs[i],f=fa[w]; tp[w]=h[f]?tp[f]:f; h[w]=h[f]+1; ans+=h[w]*pv+F1[tp[w]]; for(int j=pv;j<i;j++)ans+=dis(w,xs[j]); ANS[i]=ans; if(i%B==B-1){ pv=i+1; rebuild(); } } for(int i=0;i<n;++i)_(ANS[i]); fwrite(buf,1,ptr-buf,stdout); return 0; }
时间: 2024-11-08 03:59:13