一个初始为空的二叉搜索树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个数,对应添加当前元素后,每对节点之间的距离之和。
先把树求出来。。具体的话就是每次添加元素之后,找到这个数的前驱后继,哪个有空位这个元素就在哪。随便写个什么数据结构。
求节点的距离和的话。。我写了点分治,每次查找完往里面加点...查找啊去重啊什么的都是一样的套路...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #include<cstdlib> 8 #include<bitset> 9 //#include<ctime> 10 #define ll long long 11 #define ull unsigned long long 12 #define ui unsigned int 13 #define d double 14 //#define ld long double 15 using namespace std; 16 const int maxn=100233,mxnode=maxn; 17 struct zs{int too,pre;}e[maxn<<1];int tot,last[maxn]; 18 int lc[mxnode],rc[mxnode],v[mxnode],rnd[mxnode],tt;int V,PRE,AFT,rt;bool u[maxn][2]; 19 int sz[maxn],mx[maxn],RT,POI,dis[maxn],st[maxn],top,mxdep[maxn];bool del[maxn]; 20 int bel[maxn][20],belson[maxn<<1][20],dist[maxn][20],_sz[maxn],_sonsz[maxn<<1];int ID; 21 ll _sum[maxn],_sonsum[maxn<<1]; 22 int a[maxn]; 23 int i,j,k,n,m; 24 25 int ra,fh;char rx; 26 inline int read(){ 27 rx=getchar(),ra=0,fh=1; 28 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 29 if(rx=='-')fh=-1,rx=getchar(); 30 while(rx>='0'&&rx<='9')ra=ra*10+rx-48,rx=getchar();return ra*fh; 31 } 32 inline void maxs(int &a,int b){if(b>a)a=b;} 33 inline void lturn(int &x){int R=rc[x];rc[x]=lc[R],lc[R]=x,x=R;} 34 inline void rturn(int &x){int L=lc[x];lc[x]=rc[L],rc[L]=x,x=L;} 35 inline void insert(int &x){ 36 if(!x){x=++tt,v[x]=V,rnd[x]=rand();return;} 37 if(V<v[x]){ 38 insert(lc[x]); 39 if(rnd[lc[x]]<rnd[x])rturn(x); 40 }else{ 41 insert(rc[x]); 42 if(rnd[rc[x]]<rnd[x])lturn(x); 43 } 44 } 45 void getpre(int x){ 46 if(!x)return; 47 if(v[x]<V)PRE=v[x],getpre(rc[x]);else getpre(lc[x]); 48 } 49 void getaft(int x){ 50 if(!x)return; 51 if(v[x]>V)AFT=v[x],getaft(lc[x]);else getaft(rc[x]); 52 } 53 inline void ins(int a,int b){ 54 e[++tot].too=b,e[tot].pre=last[a],last[a]=tot; 55 e[++tot].too=a,e[tot].pre=last[b],last[b]=tot; 56 } 57 58 59 void getrt(int x,int fa){ 60 sz[x]=1,mx[x]=0; 61 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too]) 62 getrt(e[i].too,x),maxs(mx[x],sz[e[i].too]),sz[x]+=sz[e[i].too]; 63 maxs(mx[x],POI-sz[x]); 64 if(mx[x]<mx[RT])RT=x; 65 } 66 void getpoi(int x,int fa){ 67 dis[x]=dis[fa]+1,st[++top]=x,sz[x]=1; 68 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too]) 69 getpoi(e[i].too,x),sz[x]+=sz[e[i].too]; 70 } 71 void work(int x,int dep){ 72 int i,p; 73 RT=0,getrt(x,0),x=RT,mxdep[x]=dep,bel[x][dep]=x,dist[x][dep]=dis[x]=0; 74 for(i=last[x];i;i=e[i].pre)if(!del[e[i].too]){ 75 getpoi(e[i].too,x);ID++; 76 while(top)p=st[top--],bel[p][dep]=x,belson[p][dep]=ID,dist[p][dep]=dis[p]; 77 } 78 del[x]=1,sz[x]=-233; 79 for(i=last[x];i;i=e[i].pre)if(!del[e[i].too]) 80 POI=sz[e[i].too],work(e[i].too,dep+1); 81 } 82 83 int main(){ 84 n=read(); 85 for(i=1;i<=n;i++){ 86 a[i]=read(); 87 if(i>1){ 88 PRE=AFT=0,V=a[i],getpre(rt),getaft(rt), 89 insert(rt); 90 if(!PRE||!AFT)ins(PRE|AFT,a[i]),u[PRE|AFT][PRE>0]=1; 91 else if(!u[PRE][1])u[PRE][1]=1,ins(PRE,a[i]); 92 else u[AFT][0]=1,ins(AFT,a[i]); 93 }else V=a[i],insert(rt); 94 } 95 // for(i=1;i<=n;i++)for(j=last[i];j;j=e[j].pre)printf("%d-->%d ",i,e[j].too); 96 97 mx[0]=1<<30,POI=n,work(a[1],1);ll ans=0;int fa,son,dis; 98 for(i=1;i<=n;i++){ 99 k=a[i]; 100 101 ans+=_sum[k],_sz[k]++; 102 for(j=mxdep[k]-1;j;j--) 103 fa=bel[k][j],son=belson[k][j],dis=dist[k][j], 104 ans+=1ll*dis*(_sz[fa]-_sonsz[son])+_sum[fa]-_sonsum[son], 105 _sz[fa]++,_sonsz[son]++,_sum[fa]+=dis,_sonsum[son]+=dis; 106 107 printf("%lld ",ans); 108 } 109 }